blob: ac8007169bcc63cef4e3e917acdff4af8d721e18 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import static android.os.LocalPowerManager.CHEEK_EVENT;
20import static android.os.LocalPowerManager.OTHER_EVENT;
21import static android.os.LocalPowerManager.TOUCH_EVENT;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -070022import static android.os.LocalPowerManager.LONG_TOUCH_EVENT;
23import static android.os.LocalPowerManager.TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
25import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
26import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070027import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
29import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -070030import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
32import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
33import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070034import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
36import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
38import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
39import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
40import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
41import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070042import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
44import com.android.internal.app.IBatteryStats;
45import com.android.internal.policy.PolicyManager;
46import com.android.internal.view.IInputContext;
47import com.android.internal.view.IInputMethodClient;
48import com.android.internal.view.IInputMethodManager;
49import com.android.server.KeyInputQueue.QueuedEvent;
50import com.android.server.am.BatteryStatsService;
51
52import android.Manifest;
53import android.app.ActivityManagerNative;
54import android.app.IActivityManager;
55import android.content.Context;
56import android.content.pm.ActivityInfo;
57import android.content.pm.PackageManager;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070058import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.res.Configuration;
60import android.graphics.Matrix;
61import android.graphics.PixelFormat;
62import android.graphics.Rect;
63import android.graphics.Region;
64import android.os.BatteryStats;
65import android.os.Binder;
66import android.os.Debug;
67import android.os.Handler;
68import android.os.IBinder;
Michael Chan53071d62009-05-13 17:29:48 -070069import android.os.LatencyTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.os.LocalPowerManager;
71import android.os.Looper;
72import android.os.Message;
73import android.os.Parcel;
74import android.os.ParcelFileDescriptor;
75import android.os.Power;
76import android.os.PowerManager;
77import android.os.Process;
78import android.os.RemoteException;
79import android.os.ServiceManager;
80import android.os.SystemClock;
81import android.os.SystemProperties;
82import android.os.TokenWatcher;
83import android.provider.Settings;
Dianne Hackborn723738c2009-06-25 19:48:04 -070084import android.util.DisplayMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.util.EventLog;
86import android.util.Log;
87import android.util.SparseIntArray;
88import android.view.Display;
89import android.view.Gravity;
90import android.view.IApplicationToken;
91import android.view.IOnKeyguardExitResult;
92import android.view.IRotationWatcher;
93import android.view.IWindow;
94import android.view.IWindowManager;
95import android.view.IWindowSession;
96import android.view.KeyEvent;
97import android.view.MotionEvent;
98import android.view.RawInputEvent;
99import android.view.Surface;
100import android.view.SurfaceSession;
101import android.view.View;
102import android.view.ViewTreeObserver;
103import android.view.WindowManager;
104import android.view.WindowManagerImpl;
105import android.view.WindowManagerPolicy;
106import android.view.WindowManager.LayoutParams;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700107import android.view.animation.AccelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.view.animation.Animation;
109import android.view.animation.AnimationUtils;
110import android.view.animation.Transformation;
111
112import java.io.BufferedWriter;
113import java.io.File;
114import java.io.FileDescriptor;
115import java.io.IOException;
116import java.io.OutputStream;
117import java.io.OutputStreamWriter;
118import java.io.PrintWriter;
119import java.io.StringWriter;
120import java.net.Socket;
121import java.util.ArrayList;
122import java.util.HashMap;
123import java.util.HashSet;
124import java.util.Iterator;
125import java.util.List;
126
127/** {@hide} */
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700128public class WindowManagerService extends IWindowManager.Stub
129 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 static final String TAG = "WindowManager";
131 static final boolean DEBUG = false;
132 static final boolean DEBUG_FOCUS = false;
133 static final boolean DEBUG_ANIM = false;
134 static final boolean DEBUG_LAYERS = false;
135 static final boolean DEBUG_INPUT = false;
136 static final boolean DEBUG_INPUT_METHOD = false;
137 static final boolean DEBUG_VISIBILITY = false;
138 static final boolean DEBUG_ORIENTATION = false;
139 static final boolean DEBUG_APP_TRANSITIONS = false;
140 static final boolean DEBUG_STARTING_WINDOW = false;
141 static final boolean DEBUG_REORDER = false;
142 static final boolean SHOW_TRANSACTIONS = false;
Michael Chan53071d62009-05-13 17:29:48 -0700143 static final boolean MEASURE_LATENCY = false;
144 static private LatencyTimer lt;
145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean PROFILE_ORIENTATION = false;
147 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700148 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
Romain Guy06882f82009-06-10 13:36:04 -0700151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 /** How long to wait for first key repeat, in milliseconds */
153 static final int KEY_REPEAT_FIRST_DELAY = 750;
Romain Guy06882f82009-06-10 13:36:04 -0700154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 /** How long to wait for subsequent key repeats, in milliseconds */
156 static final int KEY_REPEAT_DELAY = 50;
157
158 /** How much to multiply the policy's type layer, to reserve room
159 * for multiple windows of the same type and Z-ordering adjustment
160 * with TYPE_LAYER_OFFSET. */
161 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
164 * or below others in the same layer. */
165 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 /** How much to increment the layer for each window, to reserve room
168 * for effect surfaces between them.
169 */
170 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 /** The maximum length we will accept for a loaded animation duration:
173 * this is 10 seconds.
174 */
175 static final int MAX_ANIMATION_DURATION = 10*1000;
176
177 /** Amount of time (in milliseconds) to animate the dim surface from one
178 * value to another, when no window animation is driving it.
179 */
180 static final int DEFAULT_DIM_DURATION = 200;
181
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700182 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
183 * compatible windows.
184 */
185 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 /** Adjustment to time to perform a dim, to make it more dramatic.
188 */
189 static final int DIM_DURATION_MULTIPLIER = 6;
Romain Guy06882f82009-06-10 13:36:04 -0700190
Dianne Hackborncfaef692009-06-15 14:24:44 -0700191 static final int INJECT_FAILED = 0;
192 static final int INJECT_SUCCEEDED = 1;
193 static final int INJECT_NO_PERMISSION = -1;
194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 static final int UPDATE_FOCUS_NORMAL = 0;
196 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
197 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
198 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700199
Michael Chane96440f2009-05-06 10:27:36 -0700200 /** The minimum time between dispatching touch events. */
201 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
202
203 // Last touch event time
204 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700205
Michael Chane96440f2009-05-06 10:27:36 -0700206 // Last touch event type
207 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700208
Michael Chane96440f2009-05-06 10:27:36 -0700209 // Time to wait before calling useractivity again. This saves CPU usage
210 // when we get a flood of touch events.
211 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
212
213 // Last time we call user activity
214 long mLastUserActivityCallTime = 0;
215
Romain Guy06882f82009-06-10 13:36:04 -0700216 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700217 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700220 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
222 /**
223 * Condition waited on by {@link #reenableKeyguard} to know the call to
224 * the window policy has finished.
225 */
226 private boolean mWaitingUntilKeyguardReenabled = false;
227
228
229 final TokenWatcher mKeyguardDisabled = new TokenWatcher(
230 new Handler(), "WindowManagerService.mKeyguardDisabled") {
231 public void acquired() {
232 mPolicy.enableKeyguard(false);
233 }
234 public void released() {
235 synchronized (mKeyguardDisabled) {
236 mPolicy.enableKeyguard(true);
237 mWaitingUntilKeyguardReenabled = false;
238 mKeyguardDisabled.notifyAll();
239 }
240 }
241 };
242
243 final Context mContext;
244
245 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
250
251 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 /**
256 * All currently active sessions with clients.
257 */
258 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 /**
261 * Mapping from an IWindow IBinder to the server's Window object.
262 * This is also used as the lock for all of our state.
263 */
264 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
265
266 /**
267 * Mapping from a token IBinder to a WindowToken object.
268 */
269 final HashMap<IBinder, WindowToken> mTokenMap =
270 new HashMap<IBinder, WindowToken>();
271
272 /**
273 * The same tokens as mTokenMap, stored in a list for efficient iteration
274 * over them.
275 */
276 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 /**
279 * Window tokens that are in the process of exiting, but still
280 * on screen for animations.
281 */
282 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
283
284 /**
285 * Z-ordered (bottom-most first) list of all application tokens, for
286 * controlling the ordering of windows in different applications. This
287 * contains WindowToken objects.
288 */
289 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
290
291 /**
292 * Application tokens that are in the process of exiting, but still
293 * on screen for animations.
294 */
295 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
296
297 /**
298 * List of window tokens that have finished starting their application,
299 * and now need to have the policy remove their windows.
300 */
301 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
302
303 /**
304 * Z-ordered (bottom-most first) list of all Window objects.
305 */
306 final ArrayList mWindows = new ArrayList();
307
308 /**
309 * Windows that are being resized. Used so we can tell the client about
310 * the resize after closing the transaction in which we resized the
311 * underlying surface.
312 */
313 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
314
315 /**
316 * Windows whose animations have ended and now must be removed.
317 */
318 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
319
320 /**
321 * Windows whose surface should be destroyed.
322 */
323 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
324
325 /**
326 * Windows that have lost input focus and are waiting for the new
327 * focus window to be displayed before they are told about this.
328 */
329 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
330
331 /**
332 * This is set when we have run out of memory, and will either be an empty
333 * list or contain windows that need to be force removed.
334 */
335 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700340 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 Surface mBlurSurface;
342 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 final float[] mTmpFloats = new float[9];
347
348 boolean mSafeMode;
349 boolean mDisplayEnabled = false;
350 boolean mSystemBooted = false;
351 int mRotation = 0;
352 int mRequestedRotation = 0;
353 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700354 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 ArrayList<IRotationWatcher> mRotationWatchers
356 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 boolean mLayoutNeeded = true;
359 boolean mAnimationPending = false;
360 boolean mDisplayFrozen = false;
361 boolean mWindowsFreezingScreen = false;
362 long mFreezeGcPending = 0;
363 int mAppsFreezingScreen = 0;
364
365 // This is held as long as we have the screen frozen, to give us time to
366 // perform a rotation animation when turning off shows the lock screen which
367 // changes the orientation.
368 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 // State management of app transitions. When we are preparing for a
371 // transition, mNextAppTransition will be the kind of transition to
372 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
373 // mOpeningApps and mClosingApps are the lists of tokens that will be
374 // made visible or hidden at the next transition.
375 int mNextAppTransition = WindowManagerPolicy.TRANSIT_NONE;
376 boolean mAppTransitionReady = false;
377 boolean mAppTransitionTimeout = false;
378 boolean mStartingIconInTransition = false;
379 boolean mSkipAppTransitionAnimation = false;
380 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
381 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 //flag to detect fat touch events
384 boolean mFatTouch = false;
385 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 H mH = new H();
388
389 WindowState mCurrentFocus = null;
390 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 // This just indicates the window the input method is on top of, not
393 // necessarily the window its input is going to.
394 WindowState mInputMethodTarget = null;
395 WindowState mUpcomingInputMethodTarget = null;
396 boolean mInputMethodTargetWaitingAnim;
397 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 WindowState mInputMethodWindow = null;
400 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
401
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700402 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
403
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700404 // If non-null, this is the currently visible window that is associated
405 // with the wallpaper.
406 WindowState mWallpaperTarget = null;
407 int mWallpaperAnimLayerAdjustment;
408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 AppWindowToken mFocusedApp = null;
410
411 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 float mWindowAnimationScale = 1.0f;
414 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 final KeyWaiter mKeyWaiter = new KeyWaiter();
417 final KeyQ mQueue;
418 final InputDispatcherThread mInputThread;
419
420 // Who is holding the screen on.
421 Session mHoldingScreenOn;
Romain Guy06882f82009-06-10 13:36:04 -0700422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 /**
424 * Whether the UI is currently running in touch mode (not showing
425 * navigational focus because the user is directly pressing the screen).
426 */
427 boolean mInTouchMode = false;
428
429 private ViewServer mViewServer;
430
431 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700432
Dianne Hackbornc485a602009-03-24 22:39:49 -0700433 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700434 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700435
436 // The frame use to limit the size of the app running in compatibility mode.
437 Rect mCompatibleScreenFrame = new Rect();
438 // The surface used to fill the outer rim of the app running in compatibility mode.
439 Surface mBackgroundFillerSurface = null;
440 boolean mBackgroundFillerShown = false;
441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 public static WindowManagerService main(Context context,
443 PowerManagerService pm, boolean haveInputMethods) {
444 WMThread thr = new WMThread(context, pm, haveInputMethods);
445 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 synchronized (thr) {
448 while (thr.mService == null) {
449 try {
450 thr.wait();
451 } catch (InterruptedException e) {
452 }
453 }
454 }
Romain Guy06882f82009-06-10 13:36:04 -0700455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 return thr.mService;
457 }
Romain Guy06882f82009-06-10 13:36:04 -0700458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 static class WMThread extends Thread {
460 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 private final Context mContext;
463 private final PowerManagerService mPM;
464 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 public WMThread(Context context, PowerManagerService pm,
467 boolean haveInputMethods) {
468 super("WindowManager");
469 mContext = context;
470 mPM = pm;
471 mHaveInputMethods = haveInputMethods;
472 }
Romain Guy06882f82009-06-10 13:36:04 -0700473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 public void run() {
475 Looper.prepare();
476 WindowManagerService s = new WindowManagerService(mContext, mPM,
477 mHaveInputMethods);
478 android.os.Process.setThreadPriority(
479 android.os.Process.THREAD_PRIORITY_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -0700480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 synchronized (this) {
482 mService = s;
483 notifyAll();
484 }
Romain Guy06882f82009-06-10 13:36:04 -0700485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 Looper.loop();
487 }
488 }
489
490 static class PolicyThread extends Thread {
491 private final WindowManagerPolicy mPolicy;
492 private final WindowManagerService mService;
493 private final Context mContext;
494 private final PowerManagerService mPM;
495 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 public PolicyThread(WindowManagerPolicy policy,
498 WindowManagerService service, Context context,
499 PowerManagerService pm) {
500 super("WindowManagerPolicy");
501 mPolicy = policy;
502 mService = service;
503 mContext = context;
504 mPM = pm;
505 }
Romain Guy06882f82009-06-10 13:36:04 -0700506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 public void run() {
508 Looper.prepare();
509 //Looper.myLooper().setMessageLogging(new LogPrinter(
510 // Log.VERBOSE, "WindowManagerPolicy"));
511 android.os.Process.setThreadPriority(
512 android.os.Process.THREAD_PRIORITY_FOREGROUND);
513 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 synchronized (this) {
516 mRunning = true;
517 notifyAll();
518 }
Romain Guy06882f82009-06-10 13:36:04 -0700519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 Looper.loop();
521 }
522 }
523
524 private WindowManagerService(Context context, PowerManagerService pm,
525 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700526 if (MEASURE_LATENCY) {
527 lt = new LatencyTimer(100, 1000);
528 }
529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 mContext = context;
531 mHaveInputMethods = haveInputMethods;
532 mLimitedAlphaCompositing = context.getResources().getBoolean(
533 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 mPowerManager = pm;
536 mPowerManager.setPolicy(mPolicy);
537 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
538 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
539 "SCREEN_FROZEN");
540 mScreenFrozenLock.setReferenceCounted(false);
541
542 mActivityManager = ActivityManagerNative.getDefault();
543 mBatteryStats = BatteryStatsService.getService();
544
545 // Get persisted window scale setting
546 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
547 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
548 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
549 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700550
Michael Chan9f028e62009-08-04 17:37:46 -0700551 int max_events_per_sec = 35;
552 try {
553 max_events_per_sec = Integer.parseInt(SystemProperties
554 .get("windowsmgr.max_events_per_sec"));
555 if (max_events_per_sec < 1) {
556 max_events_per_sec = 35;
557 }
558 } catch (NumberFormatException e) {
559 }
560 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 mQueue = new KeyQ();
563
564 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
567 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 synchronized (thr) {
570 while (!thr.mRunning) {
571 try {
572 thr.wait();
573 } catch (InterruptedException e) {
574 }
575 }
576 }
Romain Guy06882f82009-06-10 13:36:04 -0700577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 mInputThread.start();
Romain Guy06882f82009-06-10 13:36:04 -0700579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 // Add ourself to the Watchdog monitors.
581 Watchdog.getInstance().addMonitor(this);
582 }
583
584 @Override
585 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
586 throws RemoteException {
587 try {
588 return super.onTransact(code, data, reply, flags);
589 } catch (RuntimeException e) {
590 // The window manager only throws security exceptions, so let's
591 // log all others.
592 if (!(e instanceof SecurityException)) {
593 Log.e(TAG, "Window Manager Crash", e);
594 }
595 throw e;
596 }
597 }
598
599 private void placeWindowAfter(Object pos, WindowState window) {
600 final int i = mWindows.indexOf(pos);
601 if (localLOGV || DEBUG_FOCUS) Log.v(
602 TAG, "Adding window " + window + " at "
603 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
604 mWindows.add(i+1, window);
605 }
606
607 private void placeWindowBefore(Object pos, WindowState window) {
608 final int i = mWindows.indexOf(pos);
609 if (localLOGV || DEBUG_FOCUS) Log.v(
610 TAG, "Adding window " + window + " at "
611 + i + " of " + mWindows.size() + " (before " + pos + ")");
612 mWindows.add(i, window);
613 }
614
615 //This method finds out the index of a window that has the same app token as
616 //win. used for z ordering the windows in mWindows
617 private int findIdxBasedOnAppTokens(WindowState win) {
618 //use a local variable to cache mWindows
619 ArrayList localmWindows = mWindows;
620 int jmax = localmWindows.size();
621 if(jmax == 0) {
622 return -1;
623 }
624 for(int j = (jmax-1); j >= 0; j--) {
625 WindowState wentry = (WindowState)localmWindows.get(j);
626 if(wentry.mAppToken == win.mAppToken) {
627 return j;
628 }
629 }
630 return -1;
631 }
Romain Guy06882f82009-06-10 13:36:04 -0700632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
634 final IWindow client = win.mClient;
635 final WindowToken token = win.mToken;
636 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 final int N = localmWindows.size();
639 final WindowState attached = win.mAttachedWindow;
640 int i;
641 if (attached == null) {
642 int tokenWindowsPos = token.windows.size();
643 if (token.appWindowToken != null) {
644 int index = tokenWindowsPos-1;
645 if (index >= 0) {
646 // If this application has existing windows, we
647 // simply place the new window on top of them... but
648 // keep the starting window on top.
649 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
650 // Base windows go behind everything else.
651 placeWindowBefore(token.windows.get(0), win);
652 tokenWindowsPos = 0;
653 } else {
654 AppWindowToken atoken = win.mAppToken;
655 if (atoken != null &&
656 token.windows.get(index) == atoken.startingWindow) {
657 placeWindowBefore(token.windows.get(index), win);
658 tokenWindowsPos--;
659 } else {
660 int newIdx = findIdxBasedOnAppTokens(win);
661 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700662 //there is a window above this one associated with the same
663 //apptoken note that the window could be a floating window
664 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 //windows associated with this token.
666 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 }
669 }
670 } else {
671 if (localLOGV) Log.v(
672 TAG, "Figuring out where to add app window "
673 + client.asBinder() + " (token=" + token + ")");
674 // Figure out where the window should go, based on the
675 // order of applications.
676 final int NA = mAppTokens.size();
677 Object pos = null;
678 for (i=NA-1; i>=0; i--) {
679 AppWindowToken t = mAppTokens.get(i);
680 if (t == token) {
681 i--;
682 break;
683 }
684 if (t.windows.size() > 0) {
685 pos = t.windows.get(0);
686 }
687 }
688 // We now know the index into the apps. If we found
689 // an app window above, that gives us the position; else
690 // we need to look some more.
691 if (pos != null) {
692 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700693 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 mTokenMap.get(((WindowState)pos).mClient.asBinder());
695 if (atoken != null) {
696 final int NC = atoken.windows.size();
697 if (NC > 0) {
698 WindowState bottom = atoken.windows.get(0);
699 if (bottom.mSubLayer < 0) {
700 pos = bottom;
701 }
702 }
703 }
704 placeWindowBefore(pos, win);
705 } else {
706 while (i >= 0) {
707 AppWindowToken t = mAppTokens.get(i);
708 final int NW = t.windows.size();
709 if (NW > 0) {
710 pos = t.windows.get(NW-1);
711 break;
712 }
713 i--;
714 }
715 if (pos != null) {
716 // Move in front of any windows attached to this
717 // one.
718 WindowToken atoken =
719 mTokenMap.get(((WindowState)pos).mClient.asBinder());
720 if (atoken != null) {
721 final int NC = atoken.windows.size();
722 if (NC > 0) {
723 WindowState top = atoken.windows.get(NC-1);
724 if (top.mSubLayer >= 0) {
725 pos = top;
726 }
727 }
728 }
729 placeWindowAfter(pos, win);
730 } else {
731 // Just search for the start of this layer.
732 final int myLayer = win.mBaseLayer;
733 for (i=0; i<N; i++) {
734 WindowState w = (WindowState)localmWindows.get(i);
735 if (w.mBaseLayer > myLayer) {
736 break;
737 }
738 }
739 if (localLOGV || DEBUG_FOCUS) Log.v(
740 TAG, "Adding window " + win + " at "
741 + i + " of " + N);
742 localmWindows.add(i, win);
743 }
744 }
745 }
746 } else {
747 // Figure out where window should go, based on layer.
748 final int myLayer = win.mBaseLayer;
749 for (i=N-1; i>=0; i--) {
750 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
751 i++;
752 break;
753 }
754 }
755 if (i < 0) i = 0;
756 if (localLOGV || DEBUG_FOCUS) Log.v(
757 TAG, "Adding window " + win + " at "
758 + i + " of " + N);
759 localmWindows.add(i, win);
760 }
761 if (addToToken) {
762 token.windows.add(tokenWindowsPos, win);
763 }
764
765 } else {
766 // Figure out this window's ordering relative to the window
767 // it is attached to.
768 final int NA = token.windows.size();
769 final int sublayer = win.mSubLayer;
770 int largestSublayer = Integer.MIN_VALUE;
771 WindowState windowWithLargestSublayer = null;
772 for (i=0; i<NA; i++) {
773 WindowState w = token.windows.get(i);
774 final int wSublayer = w.mSubLayer;
775 if (wSublayer >= largestSublayer) {
776 largestSublayer = wSublayer;
777 windowWithLargestSublayer = w;
778 }
779 if (sublayer < 0) {
780 // For negative sublayers, we go below all windows
781 // in the same sublayer.
782 if (wSublayer >= sublayer) {
783 if (addToToken) {
784 token.windows.add(i, win);
785 }
786 placeWindowBefore(
787 wSublayer >= 0 ? attached : w, win);
788 break;
789 }
790 } else {
791 // For positive sublayers, we go above all windows
792 // in the same sublayer.
793 if (wSublayer > sublayer) {
794 if (addToToken) {
795 token.windows.add(i, win);
796 }
797 placeWindowBefore(w, win);
798 break;
799 }
800 }
801 }
802 if (i >= NA) {
803 if (addToToken) {
804 token.windows.add(win);
805 }
806 if (sublayer < 0) {
807 placeWindowBefore(attached, win);
808 } else {
809 placeWindowAfter(largestSublayer >= 0
810 ? windowWithLargestSublayer
811 : attached,
812 win);
813 }
814 }
815 }
Romain Guy06882f82009-06-10 13:36:04 -0700816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 if (win.mAppToken != null && addToToken) {
818 win.mAppToken.allAppWindows.add(win);
819 }
820 }
Romain Guy06882f82009-06-10 13:36:04 -0700821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 static boolean canBeImeTarget(WindowState w) {
823 final int fl = w.mAttrs.flags
824 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
825 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
826 return w.isVisibleOrAdding();
827 }
828 return false;
829 }
Romain Guy06882f82009-06-10 13:36:04 -0700830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
832 final ArrayList localmWindows = mWindows;
833 final int N = localmWindows.size();
834 WindowState w = null;
835 int i = N;
836 while (i > 0) {
837 i--;
838 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 //Log.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
841 // + Integer.toHexString(w.mAttrs.flags));
842 if (canBeImeTarget(w)) {
843 //Log.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 // Yet more tricksyness! If this window is a "starting"
846 // window, we do actually want to be on top of it, but
847 // it is not -really- where input will go. So if the caller
848 // is not actually looking to move the IME, look down below
849 // for a real window to target...
850 if (!willMove
851 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
852 && i > 0) {
853 WindowState wb = (WindowState)localmWindows.get(i-1);
854 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
855 i--;
856 w = wb;
857 }
858 }
859 break;
860 }
861 }
Romain Guy06882f82009-06-10 13:36:04 -0700862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Desired input method target="
866 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 if (willMove && w != null) {
869 final WindowState curTarget = mInputMethodTarget;
870 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 // Now some fun for dealing with window animations that
873 // modify the Z order. We need to look at all windows below
874 // the current target that are in this app, finding the highest
875 // visible one in layering.
876 AppWindowToken token = curTarget.mAppToken;
877 WindowState highestTarget = null;
878 int highestPos = 0;
879 if (token.animating || token.animation != null) {
880 int pos = 0;
881 pos = localmWindows.indexOf(curTarget);
882 while (pos >= 0) {
883 WindowState win = (WindowState)localmWindows.get(pos);
884 if (win.mAppToken != token) {
885 break;
886 }
887 if (!win.mRemoved) {
888 if (highestTarget == null || win.mAnimLayer >
889 highestTarget.mAnimLayer) {
890 highestTarget = win;
891 highestPos = pos;
892 }
893 }
894 pos--;
895 }
896 }
Romain Guy06882f82009-06-10 13:36:04 -0700897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 if (highestTarget != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700899 if (DEBUG_INPUT_METHOD) Log.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 + mNextAppTransition + " " + highestTarget
901 + " animating=" + highestTarget.isAnimating()
902 + " layer=" + highestTarget.mAnimLayer
903 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -0700904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
906 // If we are currently setting up for an animation,
907 // hold everything until we can find out what will happen.
908 mInputMethodTargetWaitingAnim = true;
909 mInputMethodTarget = highestTarget;
910 return highestPos + 1;
911 } else if (highestTarget.isAnimating() &&
912 highestTarget.mAnimLayer > w.mAnimLayer) {
913 // If the window we are currently targeting is involved
914 // with an animation, and it is on top of the next target
915 // we will be over, then hold off on moving until
916 // that is done.
917 mInputMethodTarget = highestTarget;
918 return highestPos + 1;
919 }
920 }
921 }
922 }
Romain Guy06882f82009-06-10 13:36:04 -0700923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 //Log.i(TAG, "Placing input method @" + (i+1));
925 if (w != null) {
926 if (willMove) {
927 RuntimeException e = new RuntimeException();
928 e.fillInStackTrace();
929 if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
930 + mInputMethodTarget + " to " + w, e);
931 mInputMethodTarget = w;
932 if (w.mAppToken != null) {
933 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
934 } else {
935 setInputMethodAnimLayerAdjustment(0);
936 }
937 }
938 return i+1;
939 }
940 if (willMove) {
941 RuntimeException e = new RuntimeException();
942 e.fillInStackTrace();
943 if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
944 + mInputMethodTarget + " to null", e);
945 mInputMethodTarget = null;
946 setInputMethodAnimLayerAdjustment(0);
947 }
948 return -1;
949 }
Romain Guy06882f82009-06-10 13:36:04 -0700950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 void addInputMethodWindowToListLocked(WindowState win) {
952 int pos = findDesiredInputMethodWindowIndexLocked(true);
953 if (pos >= 0) {
954 win.mTargetAppToken = mInputMethodTarget.mAppToken;
955 mWindows.add(pos, win);
956 moveInputMethodDialogsLocked(pos+1);
957 return;
958 }
959 win.mTargetAppToken = null;
960 addWindowToListInOrderLocked(win, true);
961 moveInputMethodDialogsLocked(pos);
962 }
Romain Guy06882f82009-06-10 13:36:04 -0700963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 void setInputMethodAnimLayerAdjustment(int adj) {
965 if (DEBUG_LAYERS) Log.v(TAG, "Setting im layer adj to " + adj);
966 mInputMethodAnimLayerAdjustment = adj;
967 WindowState imw = mInputMethodWindow;
968 if (imw != null) {
969 imw.mAnimLayer = imw.mLayer + adj;
970 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + imw
971 + " anim layer: " + imw.mAnimLayer);
972 int wi = imw.mChildWindows.size();
973 while (wi > 0) {
974 wi--;
975 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
976 cw.mAnimLayer = cw.mLayer + adj;
977 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + cw
978 + " anim layer: " + cw.mAnimLayer);
979 }
980 }
981 int di = mInputMethodDialogs.size();
982 while (di > 0) {
983 di --;
984 imw = mInputMethodDialogs.get(di);
985 imw.mAnimLayer = imw.mLayer + adj;
986 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + imw
987 + " anim layer: " + imw.mAnimLayer);
988 }
989 }
Romain Guy06882f82009-06-10 13:36:04 -0700990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
992 int wpos = mWindows.indexOf(win);
993 if (wpos >= 0) {
994 if (wpos < interestingPos) interestingPos--;
995 mWindows.remove(wpos);
996 int NC = win.mChildWindows.size();
997 while (NC > 0) {
998 NC--;
999 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1000 int cpos = mWindows.indexOf(cw);
1001 if (cpos >= 0) {
1002 if (cpos < interestingPos) interestingPos--;
1003 mWindows.remove(cpos);
1004 }
1005 }
1006 }
1007 return interestingPos;
1008 }
Romain Guy06882f82009-06-10 13:36:04 -07001009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 private void reAddWindowToListInOrderLocked(WindowState win) {
1011 addWindowToListInOrderLocked(win, false);
1012 // This is a hack to get all of the child windows added as well
1013 // at the right position. Child windows should be rare and
1014 // this case should be rare, so it shouldn't be that big a deal.
1015 int wpos = mWindows.indexOf(win);
1016 if (wpos >= 0) {
1017 mWindows.remove(wpos);
1018 reAddWindowLocked(wpos, win);
1019 }
1020 }
Romain Guy06882f82009-06-10 13:36:04 -07001021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 void logWindowList(String prefix) {
1023 int N = mWindows.size();
1024 while (N > 0) {
1025 N--;
1026 Log.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
1027 }
1028 }
Romain Guy06882f82009-06-10 13:36:04 -07001029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 void moveInputMethodDialogsLocked(int pos) {
1031 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 final int N = dialogs.size();
1034 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1035 for (int i=0; i<N; i++) {
1036 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1037 }
1038 if (DEBUG_INPUT_METHOD) {
1039 Log.v(TAG, "Window list w/pos=" + pos);
1040 logWindowList(" ");
1041 }
Romain Guy06882f82009-06-10 13:36:04 -07001042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 if (pos >= 0) {
1044 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1045 if (pos < mWindows.size()) {
1046 WindowState wp = (WindowState)mWindows.get(pos);
1047 if (wp == mInputMethodWindow) {
1048 pos++;
1049 }
1050 }
1051 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1052 for (int i=0; i<N; i++) {
1053 WindowState win = dialogs.get(i);
1054 win.mTargetAppToken = targetAppToken;
1055 pos = reAddWindowLocked(pos, win);
1056 }
1057 if (DEBUG_INPUT_METHOD) {
1058 Log.v(TAG, "Final window list:");
1059 logWindowList(" ");
1060 }
1061 return;
1062 }
1063 for (int i=0; i<N; i++) {
1064 WindowState win = dialogs.get(i);
1065 win.mTargetAppToken = null;
1066 reAddWindowToListInOrderLocked(win);
1067 if (DEBUG_INPUT_METHOD) {
1068 Log.v(TAG, "No IM target, final list:");
1069 logWindowList(" ");
1070 }
1071 }
1072 }
Romain Guy06882f82009-06-10 13:36:04 -07001073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1075 final WindowState imWin = mInputMethodWindow;
1076 final int DN = mInputMethodDialogs.size();
1077 if (imWin == null && DN == 0) {
1078 return false;
1079 }
Romain Guy06882f82009-06-10 13:36:04 -07001080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1082 if (imPos >= 0) {
1083 // In this case, the input method windows are to be placed
1084 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 // First check to see if the input method windows are already
1087 // located here, and contiguous.
1088 final int N = mWindows.size();
1089 WindowState firstImWin = imPos < N
1090 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 // Figure out the actual input method window that should be
1093 // at the bottom of their stack.
1094 WindowState baseImWin = imWin != null
1095 ? imWin : mInputMethodDialogs.get(0);
1096 if (baseImWin.mChildWindows.size() > 0) {
1097 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1098 if (cw.mSubLayer < 0) baseImWin = cw;
1099 }
Romain Guy06882f82009-06-10 13:36:04 -07001100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 if (firstImWin == baseImWin) {
1102 // The windows haven't moved... but are they still contiguous?
1103 // First find the top IM window.
1104 int pos = imPos+1;
1105 while (pos < N) {
1106 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1107 break;
1108 }
1109 pos++;
1110 }
1111 pos++;
1112 // Now there should be no more input method windows above.
1113 while (pos < N) {
1114 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1115 break;
1116 }
1117 pos++;
1118 }
1119 if (pos >= N) {
1120 // All is good!
1121 return false;
1122 }
1123 }
Romain Guy06882f82009-06-10 13:36:04 -07001124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 if (imWin != null) {
1126 if (DEBUG_INPUT_METHOD) {
1127 Log.v(TAG, "Moving IM from " + imPos);
1128 logWindowList(" ");
1129 }
1130 imPos = tmpRemoveWindowLocked(imPos, imWin);
1131 if (DEBUG_INPUT_METHOD) {
1132 Log.v(TAG, "List after moving with new pos " + imPos + ":");
1133 logWindowList(" ");
1134 }
1135 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1136 reAddWindowLocked(imPos, imWin);
1137 if (DEBUG_INPUT_METHOD) {
1138 Log.v(TAG, "List after moving IM to " + imPos + ":");
1139 logWindowList(" ");
1140 }
1141 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1142 } else {
1143 moveInputMethodDialogsLocked(imPos);
1144 }
Romain Guy06882f82009-06-10 13:36:04 -07001145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 } else {
1147 // In this case, the input method windows go in a fixed layer,
1148 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 if (imWin != null) {
1151 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Moving IM from " + imPos);
1152 tmpRemoveWindowLocked(0, imWin);
1153 imWin.mTargetAppToken = null;
1154 reAddWindowToListInOrderLocked(imWin);
1155 if (DEBUG_INPUT_METHOD) {
1156 Log.v(TAG, "List with no IM target:");
1157 logWindowList(" ");
1158 }
1159 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1160 } else {
1161 moveInputMethodDialogsLocked(-1);;
1162 }
Romain Guy06882f82009-06-10 13:36:04 -07001163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 }
Romain Guy06882f82009-06-10 13:36:04 -07001165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 if (needAssignLayers) {
1167 assignLayersLocked();
1168 }
Romain Guy06882f82009-06-10 13:36:04 -07001169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 return true;
1171 }
Romain Guy06882f82009-06-10 13:36:04 -07001172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 void adjustInputMethodDialogsLocked() {
1174 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1175 }
Romain Guy06882f82009-06-10 13:36:04 -07001176
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001177 boolean adjustWallpaperWindowsLocked() {
1178 boolean changed = false;
1179
1180 // First find top-most window that has asked to be on top of the
1181 // wallpaper; all wallpapers go behind it.
1182 final ArrayList localmWindows = mWindows;
1183 int N = localmWindows.size();
1184 WindowState w = null;
1185 int i = N;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001186 boolean visible = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001187 while (i > 0) {
1188 i--;
1189 w = (WindowState)localmWindows.get(i);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001190 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()) {
1191 visible = true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001192 break;
1193 }
1194 }
1195
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001196 if (!visible) w = null;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001197 //if (mWallpaperTarget != w) {
1198 // Log.v(TAG, "New wallpaper target: " + w);
1199 //}
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001200 mWallpaperTarget = w;
1201
1202 if (visible) {
1203 mWallpaperAnimLayerAdjustment = w.mAppToken != null
1204 ? w.mAppToken.animLayerAdjustment : 0;
1205
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001206 // Now w is the window we are supposed to be behind... but we
1207 // need to be sure to also be behind any of its attached windows,
1208 // AND any starting window associated with it.
1209 while (i > 0) {
1210 WindowState wb = (WindowState)localmWindows.get(i-1);
1211 if (wb.mAttachedWindow != w &&
1212 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1213 wb.mToken != w.mToken)) {
1214 // This window is not related to the previous one in any
1215 // interesting way, so stop here.
1216 break;
1217 }
1218 w = wb;
1219 i--;
1220 }
1221 }
1222
1223 // Okay i is the position immediately above the wallpaper. Look at
1224 // what is below it for later.
1225 w = i > 0 ? (WindowState)localmWindows.get(i-1) : null;
1226
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001227 final int dw = mDisplay.getWidth();
1228 final int dh = mDisplay.getHeight();
1229
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001230 // Start stepping backwards from here, ensuring that our wallpaper windows
1231 // are correctly placed.
1232 int curTokenIndex = mWallpaperTokens.size();
1233 while (curTokenIndex > 0) {
1234 curTokenIndex--;
1235 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1236 int curWallpaperIndex = token.windows.size();
1237 while (curWallpaperIndex > 0) {
1238 curWallpaperIndex--;
1239 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001240
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001241 if (visible) {
1242 updateWallpaperOffsetLocked(mWallpaperTarget, wallpaper, dw, dh);
1243 }
1244
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001245 // First, make sure the client has the current visibility
1246 // state.
1247 if (wallpaper.mWallpaperVisible != visible) {
1248 wallpaper.mWallpaperVisible = visible;
1249 try {
1250 if (DEBUG_VISIBILITY) Log.v(TAG,
1251 "Setting visibility of wallpaper " + wallpaper
1252 + ": " + visible);
1253 wallpaper.mClient.dispatchAppVisibility(visible);
1254 } catch (RemoteException e) {
1255 }
1256 }
1257
1258 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1259 if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper
1260 + " anim layer: " + wallpaper.mAnimLayer);
1261
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001262 // First, if this window is at the current index, then all
1263 // is well.
1264 if (wallpaper == w) {
1265 i--;
1266 w = i > 0 ? (WindowState)localmWindows.get(i-1) : null;
1267 continue;
1268 }
1269
1270 // The window didn't match... the current wallpaper window,
1271 // wherever it is, is in the wrong place, so make sure it is
1272 // not in the list.
1273 int oldIndex = localmWindows.indexOf(wallpaper);
1274 if (oldIndex >= 0) {
1275 localmWindows.remove(oldIndex);
1276 if (oldIndex < i) {
1277 i--;
1278 }
1279 }
1280
1281 // Now stick it in.
1282 localmWindows.add(i, wallpaper);
1283 changed = true;
1284 }
1285 }
1286
1287 return changed;
1288 }
1289
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001290 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001291 if (DEBUG_LAYERS) Log.v(TAG, "Setting wallpaper layer adj to " + adj);
1292 mWallpaperAnimLayerAdjustment = adj;
1293 int curTokenIndex = mWallpaperTokens.size();
1294 while (curTokenIndex > 0) {
1295 curTokenIndex--;
1296 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1297 int curWallpaperIndex = token.windows.size();
1298 while (curWallpaperIndex > 0) {
1299 curWallpaperIndex--;
1300 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1301 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
1302 if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper
1303 + " anim layer: " + wallpaper.mAnimLayer);
1304 }
1305 }
1306 }
1307
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001308 boolean updateWallpaperOffsetLocked(WindowState target,
1309 WindowState wallpaperWin, int dw, int dh) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001310 boolean changed = false;
1311 if (target.mWallpaperX >= 0) {
1312 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1313 int offset = availw > 0 ? -(int)(availw*target.mWallpaperX+.5f) : 0;
1314 changed = wallpaperWin.mXOffset != offset;
1315 if (changed) {
1316 wallpaperWin.mXOffset = offset;
1317 }
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001318 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001319 if (target.mWallpaperY >= 0) {
1320 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1321 int offset = availh > 0 ? -(int)(availh*target.mWallpaperY+.5f) : 0;
1322 if (wallpaperWin.mYOffset != offset) {
1323 changed = true;
1324 wallpaperWin.mYOffset = offset;
1325 }
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001326 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001327
1328 if (wallpaperWin.mWallpaperX != target.mWallpaperX
1329 || wallpaperWin.mWallpaperY != target.mWallpaperY) {
1330 wallpaperWin.mWallpaperX = target.mWallpaperX;
1331 wallpaperWin.mWallpaperY = target.mWallpaperY;
1332 try {
1333 wallpaperWin.mClient.dispatchWallpaperOffsets(
1334 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY);
1335 } catch (RemoteException e) {
1336 }
1337 }
1338
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001339 return changed;
1340 }
1341
1342 boolean updateWallpaperOffsetLocked() {
1343 final int dw = mDisplay.getWidth();
1344 final int dh = mDisplay.getHeight();
1345
1346 boolean changed = false;
1347
1348 WindowState target = mWallpaperTarget;
1349 if (target != null) {
1350 int curTokenIndex = mWallpaperTokens.size();
1351 while (curTokenIndex > 0) {
1352 curTokenIndex--;
1353 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1354 int curWallpaperIndex = token.windows.size();
1355 while (curWallpaperIndex > 0) {
1356 curWallpaperIndex--;
1357 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1358 if (updateWallpaperOffsetLocked(target, wallpaper, dw, dh)) {
1359 wallpaper.computeShownFrameLocked();
1360 changed = true;
1361 }
1362 }
1363 }
1364 }
1365
1366 return changed;
1367 }
1368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 public int addWindow(Session session, IWindow client,
1370 WindowManager.LayoutParams attrs, int viewVisibility,
1371 Rect outContentInsets) {
1372 int res = mPolicy.checkAddPermission(attrs);
1373 if (res != WindowManagerImpl.ADD_OKAY) {
1374 return res;
1375 }
Romain Guy06882f82009-06-10 13:36:04 -07001376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 boolean reportNewConfig = false;
1378 WindowState attachedWindow = null;
1379 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 synchronized(mWindowMap) {
1382 // Instantiating a Display requires talking with the simulator,
1383 // so don't do it until we know the system is mostly up and
1384 // running.
1385 if (mDisplay == null) {
1386 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1387 mDisplay = wm.getDefaultDisplay();
1388 mQueue.setDisplay(mDisplay);
1389 reportNewConfig = true;
1390 }
Romain Guy06882f82009-06-10 13:36:04 -07001391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 if (mWindowMap.containsKey(client.asBinder())) {
1393 Log.w(TAG, "Window " + client + " is already added");
1394 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1395 }
1396
1397 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Romain Guy06882f82009-06-10 13:36:04 -07001398 attachedWindow = windowForClientLocked(null, attrs.token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 if (attachedWindow == null) {
1400 Log.w(TAG, "Attempted to add window with token that is not a window: "
1401 + attrs.token + ". Aborting.");
1402 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1403 }
1404 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1405 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1406 Log.w(TAG, "Attempted to add window with token that is a sub-window: "
1407 + attrs.token + ". Aborting.");
1408 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1409 }
1410 }
1411
1412 boolean addToken = false;
1413 WindowToken token = mTokenMap.get(attrs.token);
1414 if (token == null) {
1415 if (attrs.type >= FIRST_APPLICATION_WINDOW
1416 && attrs.type <= LAST_APPLICATION_WINDOW) {
1417 Log.w(TAG, "Attempted to add application window with unknown token "
1418 + attrs.token + ". Aborting.");
1419 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1420 }
1421 if (attrs.type == TYPE_INPUT_METHOD) {
1422 Log.w(TAG, "Attempted to add input method window with unknown token "
1423 + attrs.token + ". Aborting.");
1424 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1425 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001426 if (attrs.type == TYPE_WALLPAPER) {
1427 Log.w(TAG, "Attempted to add wallpaper window with unknown token "
1428 + attrs.token + ". Aborting.");
1429 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 token = new WindowToken(attrs.token, -1, false);
1432 addToken = true;
1433 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1434 && attrs.type <= LAST_APPLICATION_WINDOW) {
1435 AppWindowToken atoken = token.appWindowToken;
1436 if (atoken == null) {
1437 Log.w(TAG, "Attempted to add window with non-application token "
1438 + token + ". Aborting.");
1439 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1440 } else if (atoken.removed) {
1441 Log.w(TAG, "Attempted to add window with exiting application token "
1442 + token + ". Aborting.");
1443 return WindowManagerImpl.ADD_APP_EXITING;
1444 }
1445 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1446 // No need for this guy!
1447 if (localLOGV) Log.v(
1448 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1449 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1450 }
1451 } else if (attrs.type == TYPE_INPUT_METHOD) {
1452 if (token.windowType != TYPE_INPUT_METHOD) {
1453 Log.w(TAG, "Attempted to add input method window with bad token "
1454 + attrs.token + ". Aborting.");
1455 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1456 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001457 } else if (attrs.type == TYPE_WALLPAPER) {
1458 if (token.windowType != TYPE_WALLPAPER) {
1459 Log.w(TAG, "Attempted to add wallpaper window with bad token "
1460 + attrs.token + ". Aborting.");
1461 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 }
1464
1465 win = new WindowState(session, client, token,
1466 attachedWindow, attrs, viewVisibility);
1467 if (win.mDeathRecipient == null) {
1468 // Client has apparently died, so there is no reason to
1469 // continue.
1470 Log.w(TAG, "Adding window client " + client.asBinder()
1471 + " that is dead, aborting.");
1472 return WindowManagerImpl.ADD_APP_EXITING;
1473 }
1474
1475 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 res = mPolicy.prepareAddWindowLw(win, attrs);
1478 if (res != WindowManagerImpl.ADD_OKAY) {
1479 return res;
1480 }
1481
1482 // From now on, no exceptions or errors allowed!
1483
1484 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07001485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 if (addToken) {
1489 mTokenMap.put(attrs.token, token);
1490 mTokenList.add(token);
1491 }
1492 win.attach();
1493 mWindowMap.put(client.asBinder(), win);
1494
1495 if (attrs.type == TYPE_APPLICATION_STARTING &&
1496 token.appWindowToken != null) {
1497 token.appWindowToken.startingWindow = win;
1498 }
1499
1500 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07001501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 if (attrs.type == TYPE_INPUT_METHOD) {
1503 mInputMethodWindow = win;
1504 addInputMethodWindowToListLocked(win);
1505 imMayMove = false;
1506 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
1507 mInputMethodDialogs.add(win);
1508 addWindowToListInOrderLocked(win, true);
1509 adjustInputMethodDialogsLocked();
1510 imMayMove = false;
1511 } else {
1512 addWindowToListInOrderLocked(win, true);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001513 if (attrs.type == TYPE_WALLPAPER ||
1514 (attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
1515 adjustWallpaperWindowsLocked();
1516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 }
Romain Guy06882f82009-06-10 13:36:04 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07001522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 if (mInTouchMode) {
1524 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
1525 }
1526 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
1527 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
1528 }
Romain Guy06882f82009-06-10 13:36:04 -07001529
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001530 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 if (win.canReceiveKeys()) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001532 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
1533 == true) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 imMayMove = false;
1535 }
1536 }
Romain Guy06882f82009-06-10 13:36:04 -07001537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07001539 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 }
Romain Guy06882f82009-06-10 13:36:04 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 assignLayersLocked();
1543 // Don't do layout here, the window must call
1544 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07001545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 //dump();
1547
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001548 if (focusChanged) {
1549 if (mCurrentFocus != null) {
1550 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
1551 }
1552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 if (localLOGV) Log.v(
1554 TAG, "New client " + client.asBinder()
1555 + ": window=" + win);
1556 }
1557
1558 // sendNewConfiguration() checks caller permissions so we must call it with
1559 // privilege. updateOrientationFromAppTokens() clears and resets the caller
1560 // identity anyway, so it's safe to just clear & restore around this whole
1561 // block.
1562 final long origId = Binder.clearCallingIdentity();
1563 if (reportNewConfig) {
1564 sendNewConfiguration();
1565 } else {
1566 // Update Orientation after adding a window, only if the window needs to be
1567 // displayed right away
1568 if (win.isVisibleOrAdding()) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07001569 if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 sendNewConfiguration();
1571 }
1572 }
1573 }
1574 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07001575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 return res;
1577 }
Romain Guy06882f82009-06-10 13:36:04 -07001578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 public void removeWindow(Session session, IWindow client) {
1580 synchronized(mWindowMap) {
1581 WindowState win = windowForClientLocked(session, client);
1582 if (win == null) {
1583 return;
1584 }
1585 removeWindowLocked(session, win);
1586 }
1587 }
Romain Guy06882f82009-06-10 13:36:04 -07001588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 public void removeWindowLocked(Session session, WindowState win) {
1590
1591 if (localLOGV || DEBUG_FOCUS) Log.v(
1592 TAG, "Remove " + win + " client="
1593 + Integer.toHexString(System.identityHashCode(
1594 win.mClient.asBinder()))
1595 + ", surface=" + win.mSurface);
1596
1597 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 if (DEBUG_APP_TRANSITIONS) Log.v(
1600 TAG, "Remove " + win + ": mSurface=" + win.mSurface
1601 + " mExiting=" + win.mExiting
1602 + " isAnimating=" + win.isAnimating()
1603 + " app-animation="
1604 + (win.mAppToken != null ? win.mAppToken.animation : null)
1605 + " inPendingTransaction="
1606 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
1607 + " mDisplayFrozen=" + mDisplayFrozen);
1608 // Visibility of the removed window. Will be used later to update orientation later on.
1609 boolean wasVisible = false;
1610 // First, see if we need to run an animation. If we do, we have
1611 // to hold off on removing the window until the animation is done.
1612 // If the display is frozen, just remove immediately, since the
1613 // animation wouldn't be seen.
1614 if (win.mSurface != null && !mDisplayFrozen) {
1615 // If we are not currently running the exit animation, we
1616 // need to see about starting one.
1617 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 int transit = WindowManagerPolicy.TRANSIT_EXIT;
1620 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
1621 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
1622 }
1623 // Try starting an animation.
1624 if (applyAnimationLocked(win, transit, false)) {
1625 win.mExiting = true;
1626 }
1627 }
1628 if (win.mExiting || win.isAnimating()) {
1629 // The exit animation is running... wait for it!
1630 //Log.i(TAG, "*** Running exit animation...");
1631 win.mExiting = true;
1632 win.mRemoveOnExit = true;
1633 mLayoutNeeded = true;
1634 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
1635 performLayoutAndPlaceSurfacesLocked();
1636 if (win.mAppToken != null) {
1637 win.mAppToken.updateReportedVisibilityLocked();
1638 }
1639 //dump();
1640 Binder.restoreCallingIdentity(origId);
1641 return;
1642 }
1643 }
1644
1645 removeWindowInnerLocked(session, win);
1646 // Removing a visible window will effect the computed orientation
1647 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07001648 if (wasVisible && computeForcedAppOrientationLocked()
1649 != mForcedAppOrientation) {
1650 mH.sendMessage(mH.obtainMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 }
1652 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
1653 Binder.restoreCallingIdentity(origId);
1654 }
Romain Guy06882f82009-06-10 13:36:04 -07001655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 private void removeWindowInnerLocked(Session session, WindowState win) {
1657 mKeyWaiter.releasePendingPointerLocked(win.mSession);
1658 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
Romain Guy06882f82009-06-10 13:36:04 -07001659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07001661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 if (mInputMethodTarget == win) {
1663 moveInputMethodWindowsIfNeededLocked(false);
1664 }
Romain Guy06882f82009-06-10 13:36:04 -07001665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 mPolicy.removeWindowLw(win);
1667 win.removeLocked();
1668
1669 mWindowMap.remove(win.mClient.asBinder());
1670 mWindows.remove(win);
1671
1672 if (mInputMethodWindow == win) {
1673 mInputMethodWindow = null;
1674 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
1675 mInputMethodDialogs.remove(win);
1676 }
Romain Guy06882f82009-06-10 13:36:04 -07001677
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001678 if (win.mAttrs.type == TYPE_WALLPAPER ||
1679 (win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
1680 adjustWallpaperWindowsLocked();
1681 }
1682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 final WindowToken token = win.mToken;
1684 final AppWindowToken atoken = win.mAppToken;
1685 token.windows.remove(win);
1686 if (atoken != null) {
1687 atoken.allAppWindows.remove(win);
1688 }
1689 if (localLOGV) Log.v(
1690 TAG, "**** Removing window " + win + ": count="
1691 + token.windows.size());
1692 if (token.windows.size() == 0) {
1693 if (!token.explicit) {
1694 mTokenMap.remove(token.token);
1695 mTokenList.remove(token);
1696 } else if (atoken != null) {
1697 atoken.firstWindowDrawn = false;
1698 }
1699 }
1700
1701 if (atoken != null) {
1702 if (atoken.startingWindow == win) {
1703 atoken.startingWindow = null;
1704 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
1705 // If this is the last window and we had requested a starting
1706 // transition window, well there is no point now.
1707 atoken.startingData = null;
1708 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
1709 // If this is the last window except for a starting transition
1710 // window, we need to get rid of the starting transition.
1711 if (DEBUG_STARTING_WINDOW) {
1712 Log.v(TAG, "Schedule remove starting " + token
1713 + ": no more real windows");
1714 }
1715 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
1716 mH.sendMessage(m);
1717 }
1718 }
Romain Guy06882f82009-06-10 13:36:04 -07001719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 if (!mInLayout) {
1721 assignLayersLocked();
1722 mLayoutNeeded = true;
1723 performLayoutAndPlaceSurfacesLocked();
1724 if (win.mAppToken != null) {
1725 win.mAppToken.updateReportedVisibilityLocked();
1726 }
1727 }
1728 }
1729
1730 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
1731 long origId = Binder.clearCallingIdentity();
1732 try {
1733 synchronized (mWindowMap) {
1734 WindowState w = windowForClientLocked(session, client);
1735 if ((w != null) && (w.mSurface != null)) {
1736 Surface.openTransaction();
1737 try {
1738 w.mSurface.setTransparentRegionHint(region);
1739 } finally {
1740 Surface.closeTransaction();
1741 }
1742 }
1743 }
1744 } finally {
1745 Binder.restoreCallingIdentity(origId);
1746 }
1747 }
1748
1749 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07001750 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 Rect visibleInsets) {
1752 long origId = Binder.clearCallingIdentity();
1753 try {
1754 synchronized (mWindowMap) {
1755 WindowState w = windowForClientLocked(session, client);
1756 if (w != null) {
1757 w.mGivenInsetsPending = false;
1758 w.mGivenContentInsets.set(contentInsets);
1759 w.mGivenVisibleInsets.set(visibleInsets);
1760 w.mTouchableInsets = touchableInsets;
1761 mLayoutNeeded = true;
1762 performLayoutAndPlaceSurfacesLocked();
1763 }
1764 }
1765 } finally {
1766 Binder.restoreCallingIdentity(origId);
1767 }
1768 }
Romain Guy06882f82009-06-10 13:36:04 -07001769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 public void getWindowDisplayFrame(Session session, IWindow client,
1771 Rect outDisplayFrame) {
1772 synchronized(mWindowMap) {
1773 WindowState win = windowForClientLocked(session, client);
1774 if (win == null) {
1775 outDisplayFrame.setEmpty();
1776 return;
1777 }
1778 outDisplayFrame.set(win.mDisplayFrame);
1779 }
1780 }
1781
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001782 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y) {
1783 if (window.mWallpaperX != x || window.mWallpaperY != y) {
1784 window.mWallpaperX = x;
1785 window.mWallpaperY = y;
1786
1787 if (mWallpaperTarget == window) {
1788 if (updateWallpaperOffsetLocked()) {
1789 performLayoutAndPlaceSurfacesLocked();
1790 }
1791 }
1792 }
1793 }
1794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 public int relayoutWindow(Session session, IWindow client,
1796 WindowManager.LayoutParams attrs, int requestedWidth,
1797 int requestedHeight, int viewVisibility, boolean insetsPending,
1798 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
1799 Surface outSurface) {
1800 boolean displayed = false;
1801 boolean inTouchMode;
1802 Configuration newConfig = null;
1803 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 synchronized(mWindowMap) {
1806 WindowState win = windowForClientLocked(session, client);
1807 if (win == null) {
1808 return 0;
1809 }
1810 win.mRequestedWidth = requestedWidth;
1811 win.mRequestedHeight = requestedHeight;
1812
1813 if (attrs != null) {
1814 mPolicy.adjustWindowParamsLw(attrs);
1815 }
Romain Guy06882f82009-06-10 13:36:04 -07001816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 int attrChanges = 0;
1818 int flagChanges = 0;
1819 if (attrs != null) {
1820 flagChanges = win.mAttrs.flags ^= attrs.flags;
1821 attrChanges = win.mAttrs.copyFrom(attrs);
1822 }
1823
1824 if (localLOGV) Log.v(
1825 TAG, "Relayout given client " + client.asBinder()
1826 + " (" + win.mAttrs.getTitle() + ")");
1827
1828
1829 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
1830 win.mAlpha = attrs.alpha;
1831 }
1832
1833 final boolean scaledWindow =
1834 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
1835
1836 if (scaledWindow) {
1837 // requested{Width|Height} Surface's physical size
1838 // attrs.{width|height} Size on screen
1839 win.mHScale = (attrs.width != requestedWidth) ?
1840 (attrs.width / (float)requestedWidth) : 1.0f;
1841 win.mVScale = (attrs.height != requestedHeight) ?
1842 (attrs.height / (float)requestedHeight) : 1.0f;
1843 }
1844
1845 boolean imMayMove = (flagChanges&(
1846 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
1847 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07001848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 boolean focusMayChange = win.mViewVisibility != viewVisibility
1850 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
1851 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07001852
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001853 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
1854 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
1855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 win.mRelayoutCalled = true;
1857 final int oldVisibility = win.mViewVisibility;
1858 win.mViewVisibility = viewVisibility;
1859 if (viewVisibility == View.VISIBLE &&
1860 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
1861 displayed = !win.isVisibleLw();
1862 if (win.mExiting) {
1863 win.mExiting = false;
1864 win.mAnimation = null;
1865 }
1866 if (win.mDestroying) {
1867 win.mDestroying = false;
1868 mDestroySurface.remove(win);
1869 }
1870 if (oldVisibility == View.GONE) {
1871 win.mEnterAnimationPending = true;
1872 }
1873 if (displayed && win.mSurface != null && !win.mDrawPending
1874 && !win.mCommitDrawPending && !mDisplayFrozen) {
1875 applyEnterAnimationLocked(win);
1876 }
1877 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
1878 // To change the format, we need to re-build the surface.
1879 win.destroySurfaceLocked();
1880 displayed = true;
1881 }
1882 try {
1883 Surface surface = win.createSurfaceLocked();
1884 if (surface != null) {
1885 outSurface.copyFrom(surface);
1886 } else {
1887 outSurface.clear();
1888 }
1889 } catch (Exception e) {
1890 Log.w(TAG, "Exception thrown when creating surface for client "
1891 + client + " (" + win.mAttrs.getTitle() + ")",
1892 e);
1893 Binder.restoreCallingIdentity(origId);
1894 return 0;
1895 }
1896 if (displayed) {
1897 focusMayChange = true;
1898 }
1899 if (win.mAttrs.type == TYPE_INPUT_METHOD
1900 && mInputMethodWindow == null) {
1901 mInputMethodWindow = win;
1902 imMayMove = true;
1903 }
1904 } else {
1905 win.mEnterAnimationPending = false;
1906 if (win.mSurface != null) {
1907 // If we are not currently running the exit animation, we
1908 // need to see about starting one.
1909 if (!win.mExiting) {
1910 // Try starting an animation; if there isn't one, we
1911 // can destroy the surface right away.
1912 int transit = WindowManagerPolicy.TRANSIT_EXIT;
1913 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
1914 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
1915 }
1916 if (win.isWinVisibleLw() &&
1917 applyAnimationLocked(win, transit, false)) {
1918 win.mExiting = true;
1919 mKeyWaiter.finishedKey(session, client, true,
1920 KeyWaiter.RETURN_NOTHING);
1921 } else if (win.isAnimating()) {
1922 // Currently in a hide animation... turn this into
1923 // an exit.
1924 win.mExiting = true;
1925 } else {
1926 if (mInputMethodWindow == win) {
1927 mInputMethodWindow = null;
1928 }
1929 win.destroySurfaceLocked();
1930 }
1931 }
1932 }
1933 outSurface.clear();
1934 }
1935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 if (focusMayChange) {
1937 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
1938 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 imMayMove = false;
1940 }
1941 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
1942 }
Romain Guy06882f82009-06-10 13:36:04 -07001943
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001944 // updateFocusedWindowLocked() already assigned layers so we only need to
1945 // reassign them at this point if the IM window state gets shuffled
1946 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07001947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 if (imMayMove) {
1949 if (moveInputMethodWindowsIfNeededLocked(false)) {
1950 assignLayers = true;
1951 }
1952 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001953 if (wallpaperMayMove) {
1954 if (adjustWallpaperWindowsLocked()) {
1955 assignLayers = true;
1956 }
1957 }
Romain Guy06882f82009-06-10 13:36:04 -07001958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 mLayoutNeeded = true;
1960 win.mGivenInsetsPending = insetsPending;
1961 if (assignLayers) {
1962 assignLayersLocked();
1963 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001964 newConfig = updateOrientationFromAppTokensLocked(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 performLayoutAndPlaceSurfacesLocked();
1966 if (win.mAppToken != null) {
1967 win.mAppToken.updateReportedVisibilityLocked();
1968 }
1969 outFrame.set(win.mFrame);
1970 outContentInsets.set(win.mContentInsets);
1971 outVisibleInsets.set(win.mVisibleInsets);
1972 if (localLOGV) Log.v(
1973 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07001974 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 + ", requestedHeight=" + requestedHeight
1976 + ", viewVisibility=" + viewVisibility
1977 + "\nRelayout returning frame=" + outFrame
1978 + ", surface=" + outSurface);
1979
1980 if (localLOGV || DEBUG_FOCUS) Log.v(
1981 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
1982
1983 inTouchMode = mInTouchMode;
1984 }
1985
1986 if (newConfig != null) {
1987 sendNewConfiguration();
1988 }
Romain Guy06882f82009-06-10 13:36:04 -07001989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07001991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
1993 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
1994 }
1995
1996 public void finishDrawingWindow(Session session, IWindow client) {
1997 final long origId = Binder.clearCallingIdentity();
1998 synchronized(mWindowMap) {
1999 WindowState win = windowForClientLocked(session, client);
2000 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002001 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2002 adjustWallpaperWindowsLocked();
2003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 mLayoutNeeded = true;
2005 performLayoutAndPlaceSurfacesLocked();
2006 }
2007 }
2008 Binder.restoreCallingIdentity(origId);
2009 }
2010
2011 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
2012 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: params package="
2013 + (lp != null ? lp.packageName : null)
2014 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2015 if (lp != null && lp.windowAnimations != 0) {
2016 // If this is a system resource, don't try to load it from the
2017 // application resources. It is nice to avoid loading application
2018 // resources if we can.
2019 String packageName = lp.packageName != null ? lp.packageName : "android";
2020 int resId = lp.windowAnimations;
2021 if ((resId&0xFF000000) == 0x01000000) {
2022 packageName = "android";
2023 }
2024 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: picked package="
2025 + packageName);
2026 return AttributeCache.instance().get(packageName, resId,
2027 com.android.internal.R.styleable.WindowAnimation);
2028 }
2029 return null;
2030 }
Romain Guy06882f82009-06-10 13:36:04 -07002031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 private void applyEnterAnimationLocked(WindowState win) {
2033 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2034 if (win.mEnterAnimationPending) {
2035 win.mEnterAnimationPending = false;
2036 transit = WindowManagerPolicy.TRANSIT_ENTER;
2037 }
2038
2039 applyAnimationLocked(win, transit, true);
2040 }
2041
2042 private boolean applyAnimationLocked(WindowState win,
2043 int transit, boolean isEntrance) {
2044 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2045 // If we are trying to apply an animation, but already running
2046 // an animation of the same type, then just leave that one alone.
2047 return true;
2048 }
Romain Guy06882f82009-06-10 13:36:04 -07002049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 // Only apply an animation if the display isn't frozen. If it is
2051 // frozen, there is no reason to animate and it can cause strange
2052 // artifacts when we unfreeze the display if some different animation
2053 // is running.
2054 if (!mDisplayFrozen) {
2055 int anim = mPolicy.selectAnimationLw(win, transit);
2056 int attr = -1;
2057 Animation a = null;
2058 if (anim != 0) {
2059 a = AnimationUtils.loadAnimation(mContext, anim);
2060 } else {
2061 switch (transit) {
2062 case WindowManagerPolicy.TRANSIT_ENTER:
2063 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2064 break;
2065 case WindowManagerPolicy.TRANSIT_EXIT:
2066 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2067 break;
2068 case WindowManagerPolicy.TRANSIT_SHOW:
2069 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2070 break;
2071 case WindowManagerPolicy.TRANSIT_HIDE:
2072 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2073 break;
2074 }
2075 if (attr >= 0) {
2076 a = loadAnimation(win.mAttrs, attr);
2077 }
2078 }
2079 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: win=" + win
2080 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2081 + " mAnimation=" + win.mAnimation
2082 + " isEntrance=" + isEntrance);
2083 if (a != null) {
2084 if (DEBUG_ANIM) {
2085 RuntimeException e = new RuntimeException();
2086 e.fillInStackTrace();
2087 Log.v(TAG, "Loaded animation " + a + " for " + win, e);
2088 }
2089 win.setAnimation(a);
2090 win.mAnimationIsEntrance = isEntrance;
2091 }
2092 } else {
2093 win.clearAnimation();
2094 }
2095
2096 return win.mAnimation != null;
2097 }
2098
2099 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2100 int anim = 0;
2101 Context context = mContext;
2102 if (animAttr >= 0) {
2103 AttributeCache.Entry ent = getCachedAnimations(lp);
2104 if (ent != null) {
2105 context = ent.context;
2106 anim = ent.array.getResourceId(animAttr, 0);
2107 }
2108 }
2109 if (anim != 0) {
2110 return AnimationUtils.loadAnimation(context, anim);
2111 }
2112 return null;
2113 }
Romain Guy06882f82009-06-10 13:36:04 -07002114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002115 private boolean applyAnimationLocked(AppWindowToken wtoken,
2116 WindowManager.LayoutParams lp, int transit, boolean enter) {
2117 // Only apply an animation if the display isn't frozen. If it is
2118 // frozen, there is no reason to animate and it can cause strange
2119 // artifacts when we unfreeze the display if some different animation
2120 // is running.
2121 if (!mDisplayFrozen) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002122 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002123 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002124 a = new FadeInOutAnimation(enter);
2125 if (DEBUG_ANIM) Log.v(TAG,
2126 "applying FadeInOutAnimation for a window in compatibility mode");
2127 } else {
2128 int animAttr = 0;
2129 switch (transit) {
2130 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2131 animAttr = enter
2132 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2133 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2134 break;
2135 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2136 animAttr = enter
2137 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2138 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2139 break;
2140 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2141 animAttr = enter
2142 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2143 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2144 break;
2145 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2146 animAttr = enter
2147 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2148 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2149 break;
2150 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2151 animAttr = enter
2152 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2153 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2154 break;
2155 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2156 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002157 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002158 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2159 break;
2160 }
2161 a = loadAnimation(lp, animAttr);
2162 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken
2163 + " anim=" + a
2164 + " animAttr=0x" + Integer.toHexString(animAttr)
2165 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167 if (a != null) {
2168 if (DEBUG_ANIM) {
2169 RuntimeException e = new RuntimeException();
2170 e.fillInStackTrace();
2171 Log.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
2172 }
2173 wtoken.setAnimation(a);
2174 }
2175 } else {
2176 wtoken.clearAnimation();
2177 }
2178
2179 return wtoken.animation != null;
2180 }
2181
2182 // -------------------------------------------------------------
2183 // Application Window Tokens
2184 // -------------------------------------------------------------
2185
2186 public void validateAppTokens(List tokens) {
2187 int v = tokens.size()-1;
2188 int m = mAppTokens.size()-1;
2189 while (v >= 0 && m >= 0) {
2190 AppWindowToken wtoken = mAppTokens.get(m);
2191 if (wtoken.removed) {
2192 m--;
2193 continue;
2194 }
2195 if (tokens.get(v) != wtoken.token) {
2196 Log.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
2197 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2198 }
2199 v--;
2200 m--;
2201 }
2202 while (v >= 0) {
2203 Log.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
2204 v--;
2205 }
2206 while (m >= 0) {
2207 AppWindowToken wtoken = mAppTokens.get(m);
2208 if (!wtoken.removed) {
2209 Log.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
2210 }
2211 m--;
2212 }
2213 }
2214
2215 boolean checkCallingPermission(String permission, String func) {
2216 // Quick check: if the calling permission is me, it's all okay.
2217 if (Binder.getCallingPid() == Process.myPid()) {
2218 return true;
2219 }
Romain Guy06882f82009-06-10 13:36:04 -07002220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 if (mContext.checkCallingPermission(permission)
2222 == PackageManager.PERMISSION_GRANTED) {
2223 return true;
2224 }
2225 String msg = "Permission Denial: " + func + " from pid="
2226 + Binder.getCallingPid()
2227 + ", uid=" + Binder.getCallingUid()
2228 + " requires " + permission;
2229 Log.w(TAG, msg);
2230 return false;
2231 }
Romain Guy06882f82009-06-10 13:36:04 -07002232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 AppWindowToken findAppWindowToken(IBinder token) {
2234 WindowToken wtoken = mTokenMap.get(token);
2235 if (wtoken == null) {
2236 return null;
2237 }
2238 return wtoken.appWindowToken;
2239 }
Romain Guy06882f82009-06-10 13:36:04 -07002240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 public void addWindowToken(IBinder token, int type) {
2242 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2243 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002244 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 }
Romain Guy06882f82009-06-10 13:36:04 -07002246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 synchronized(mWindowMap) {
2248 WindowToken wtoken = mTokenMap.get(token);
2249 if (wtoken != null) {
2250 Log.w(TAG, "Attempted to add existing input method token: " + token);
2251 return;
2252 }
2253 wtoken = new WindowToken(token, type, true);
2254 mTokenMap.put(token, wtoken);
2255 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002256 if (type == TYPE_WALLPAPER) {
2257 mWallpaperTokens.add(wtoken);
2258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 }
2260 }
Romain Guy06882f82009-06-10 13:36:04 -07002261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 public void removeWindowToken(IBinder token) {
2263 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2264 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002265 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 }
2267
2268 final long origId = Binder.clearCallingIdentity();
2269 synchronized(mWindowMap) {
2270 WindowToken wtoken = mTokenMap.remove(token);
2271 mTokenList.remove(wtoken);
2272 if (wtoken != null) {
2273 boolean delayed = false;
2274 if (!wtoken.hidden) {
2275 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07002276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 final int N = wtoken.windows.size();
2278 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07002279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 for (int i=0; i<N; i++) {
2281 WindowState win = wtoken.windows.get(i);
2282
2283 if (win.isAnimating()) {
2284 delayed = true;
2285 }
Romain Guy06882f82009-06-10 13:36:04 -07002286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 if (win.isVisibleNow()) {
2288 applyAnimationLocked(win,
2289 WindowManagerPolicy.TRANSIT_EXIT, false);
2290 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2291 KeyWaiter.RETURN_NOTHING);
2292 changed = true;
2293 }
2294 }
2295
2296 if (changed) {
2297 mLayoutNeeded = true;
2298 performLayoutAndPlaceSurfacesLocked();
2299 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2300 }
Romain Guy06882f82009-06-10 13:36:04 -07002301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 if (delayed) {
2303 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002304 } else if (wtoken.windowType == TYPE_WALLPAPER) {
2305 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 }
2307 }
Romain Guy06882f82009-06-10 13:36:04 -07002308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 } else {
2310 Log.w(TAG, "Attempted to remove non-existing token: " + token);
2311 }
2312 }
2313 Binder.restoreCallingIdentity(origId);
2314 }
2315
2316 public void addAppToken(int addPos, IApplicationToken token,
2317 int groupId, int requestedOrientation, boolean fullscreen) {
2318 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2319 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002320 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 }
Romain Guy06882f82009-06-10 13:36:04 -07002322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 synchronized(mWindowMap) {
2324 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2325 if (wtoken != null) {
2326 Log.w(TAG, "Attempted to add existing app token: " + token);
2327 return;
2328 }
2329 wtoken = new AppWindowToken(token);
2330 wtoken.groupId = groupId;
2331 wtoken.appFullscreen = fullscreen;
2332 wtoken.requestedOrientation = requestedOrientation;
2333 mAppTokens.add(addPos, wtoken);
Dave Bortcfe65242009-04-09 14:51:04 -07002334 if (localLOGV) Log.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 mTokenMap.put(token.asBinder(), wtoken);
2336 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07002337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 // Application tokens start out hidden.
2339 wtoken.hidden = true;
2340 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07002341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 //dump();
2343 }
2344 }
Romain Guy06882f82009-06-10 13:36:04 -07002345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 public void setAppGroupId(IBinder token, int groupId) {
2347 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2348 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002349 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 }
2351
2352 synchronized(mWindowMap) {
2353 AppWindowToken wtoken = findAppWindowToken(token);
2354 if (wtoken == null) {
2355 Log.w(TAG, "Attempted to set group id of non-existing app token: " + token);
2356 return;
2357 }
2358 wtoken.groupId = groupId;
2359 }
2360 }
Romain Guy06882f82009-06-10 13:36:04 -07002361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 public int getOrientationFromWindowsLocked() {
2363 int pos = mWindows.size() - 1;
2364 while (pos >= 0) {
2365 WindowState wtoken = (WindowState) mWindows.get(pos);
2366 pos--;
2367 if (wtoken.mAppToken != null) {
2368 // We hit an application window. so the orientation will be determined by the
2369 // app window. No point in continuing further.
2370 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2371 }
2372 if (!wtoken.isVisibleLw()) {
2373 continue;
2374 }
2375 int req = wtoken.mAttrs.screenOrientation;
2376 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
2377 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
2378 continue;
2379 } else {
2380 return req;
2381 }
2382 }
2383 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2384 }
Romain Guy06882f82009-06-10 13:36:04 -07002385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 public int getOrientationFromAppTokensLocked() {
2387 int pos = mAppTokens.size() - 1;
2388 int curGroup = 0;
2389 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Owen Lin3413b892009-05-01 17:12:32 -07002390 boolean findingBehind = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 boolean haveGroup = false;
The Android Open Source Project4df24232009-03-05 14:34:35 -08002392 boolean lastFullscreen = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 while (pos >= 0) {
2394 AppWindowToken wtoken = mAppTokens.get(pos);
2395 pos--;
Owen Lin3413b892009-05-01 17:12:32 -07002396 // if we're about to tear down this window and not seek for
2397 // the behind activity, don't use it for orientation
2398 if (!findingBehind
2399 && (!wtoken.hidden && wtoken.hiddenRequested)) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002400 continue;
2401 }
2402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 if (!haveGroup) {
2404 // We ignore any hidden applications on the top.
2405 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
2406 continue;
2407 }
2408 haveGroup = true;
2409 curGroup = wtoken.groupId;
2410 lastOrientation = wtoken.requestedOrientation;
2411 } else if (curGroup != wtoken.groupId) {
2412 // If we have hit a new application group, and the bottom
2413 // of the previous group didn't explicitly say to use
The Android Open Source Project4df24232009-03-05 14:34:35 -08002414 // the orientation behind it, and the last app was
2415 // full screen, then we'll stick with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002416 // user's orientation.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002417 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
2418 && lastFullscreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 return lastOrientation;
2420 }
2421 }
2422 int or = wtoken.requestedOrientation;
Owen Lin3413b892009-05-01 17:12:32 -07002423 // If this application is fullscreen, and didn't explicitly say
2424 // to use the orientation behind it, then just take whatever
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 // orientation it has and ignores whatever is under it.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002426 lastFullscreen = wtoken.appFullscreen;
Romain Guy06882f82009-06-10 13:36:04 -07002427 if (lastFullscreen
Owen Lin3413b892009-05-01 17:12:32 -07002428 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 return or;
2430 }
2431 // If this application has requested an explicit orientation,
2432 // then use it.
2433 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
2434 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
2435 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
2436 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
2437 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
2438 return or;
2439 }
Owen Lin3413b892009-05-01 17:12:32 -07002440 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 }
2442 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2443 }
Romain Guy06882f82009-06-10 13:36:04 -07002444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002446 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002447 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2448 "updateOrientationFromAppTokens()")) {
2449 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2450 }
2451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 Configuration config;
2453 long ident = Binder.clearCallingIdentity();
Dianne Hackborncfaef692009-06-15 14:24:44 -07002454 config = updateOrientationFromAppTokensUnchecked(currentConfig,
2455 freezeThisOneIfNeeded);
2456 Binder.restoreCallingIdentity(ident);
2457 return config;
2458 }
2459
2460 Configuration updateOrientationFromAppTokensUnchecked(
2461 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
2462 Configuration config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 synchronized(mWindowMap) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002464 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 }
2466 if (config != null) {
2467 mLayoutNeeded = true;
2468 performLayoutAndPlaceSurfacesLocked();
2469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 return config;
2471 }
Romain Guy06882f82009-06-10 13:36:04 -07002472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 /*
2474 * The orientation is computed from non-application windows first. If none of
2475 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07002476 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
2478 * android.os.IBinder)
2479 */
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002480 Configuration updateOrientationFromAppTokensLocked(
The Android Open Source Project10592532009-03-18 17:39:46 -07002481 Configuration appConfig, IBinder freezeThisOneIfNeeded) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483 long ident = Binder.clearCallingIdentity();
2484 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002485 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07002486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 if (req != mForcedAppOrientation) {
2488 changed = true;
2489 mForcedAppOrientation = req;
2490 //send a message to Policy indicating orientation change to take
2491 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002492 mPolicy.setCurrentOrientationLw(req);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 }
Romain Guy06882f82009-06-10 13:36:04 -07002494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 if (changed) {
2496 changed = setRotationUncheckedLocked(
Dianne Hackborn321ae682009-03-27 16:16:03 -07002497 WindowManagerPolicy.USE_LAST_ROTATION,
2498 mLastRotationFlags & (~Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 if (changed) {
2500 if (freezeThisOneIfNeeded != null) {
2501 AppWindowToken wtoken = findAppWindowToken(
2502 freezeThisOneIfNeeded);
2503 if (wtoken != null) {
2504 startAppFreezingScreenLocked(wtoken,
2505 ActivityInfo.CONFIG_ORIENTATION);
2506 }
2507 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07002508 return computeNewConfigurationLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 }
2510 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002511
2512 // No obvious action we need to take, but if our current
2513 // state mismatches the activity maanager's, update it
2514 if (appConfig != null) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07002515 mTempConfiguration.setToDefaults();
2516 if (computeNewConfigurationLocked(mTempConfiguration)) {
2517 if (appConfig.diff(mTempConfiguration) != 0) {
2518 Log.i(TAG, "Config changed: " + mTempConfiguration);
2519 return new Configuration(mTempConfiguration);
2520 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002521 }
2522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 } finally {
2524 Binder.restoreCallingIdentity(ident);
2525 }
Romain Guy06882f82009-06-10 13:36:04 -07002526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 return null;
2528 }
Romain Guy06882f82009-06-10 13:36:04 -07002529
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002530 int computeForcedAppOrientationLocked() {
2531 int req = getOrientationFromWindowsLocked();
2532 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
2533 req = getOrientationFromAppTokensLocked();
2534 }
2535 return req;
2536 }
Romain Guy06882f82009-06-10 13:36:04 -07002537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002538 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
2539 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2540 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002541 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 }
Romain Guy06882f82009-06-10 13:36:04 -07002543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 synchronized(mWindowMap) {
2545 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2546 if (wtoken == null) {
2547 Log.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
2548 return;
2549 }
Romain Guy06882f82009-06-10 13:36:04 -07002550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 wtoken.requestedOrientation = requestedOrientation;
2552 }
2553 }
Romain Guy06882f82009-06-10 13:36:04 -07002554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 public int getAppOrientation(IApplicationToken token) {
2556 synchronized(mWindowMap) {
2557 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2558 if (wtoken == null) {
2559 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2560 }
Romain Guy06882f82009-06-10 13:36:04 -07002561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 return wtoken.requestedOrientation;
2563 }
2564 }
Romain Guy06882f82009-06-10 13:36:04 -07002565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
2567 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2568 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002569 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 }
2571
2572 synchronized(mWindowMap) {
2573 boolean changed = false;
2574 if (token == null) {
2575 if (DEBUG_FOCUS) Log.v(TAG, "Clearing focused app, was " + mFocusedApp);
2576 changed = mFocusedApp != null;
2577 mFocusedApp = null;
2578 mKeyWaiter.tickle();
2579 } else {
2580 AppWindowToken newFocus = findAppWindowToken(token);
2581 if (newFocus == null) {
2582 Log.w(TAG, "Attempted to set focus to non-existing app token: " + token);
2583 return;
2584 }
2585 changed = mFocusedApp != newFocus;
2586 mFocusedApp = newFocus;
2587 if (DEBUG_FOCUS) Log.v(TAG, "Set focused app to: " + mFocusedApp);
2588 mKeyWaiter.tickle();
2589 }
2590
2591 if (moveFocusNow && changed) {
2592 final long origId = Binder.clearCallingIdentity();
2593 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2594 Binder.restoreCallingIdentity(origId);
2595 }
2596 }
2597 }
2598
2599 public void prepareAppTransition(int transit) {
2600 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2601 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002602 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 }
Romain Guy06882f82009-06-10 13:36:04 -07002604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 synchronized(mWindowMap) {
2606 if (DEBUG_APP_TRANSITIONS) Log.v(
2607 TAG, "Prepare app transition: transit=" + transit
2608 + " mNextAppTransition=" + mNextAppTransition);
2609 if (!mDisplayFrozen) {
2610 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
2611 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002612 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
2613 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
2614 // Opening a new task always supersedes a close for the anim.
2615 mNextAppTransition = transit;
2616 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2617 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
2618 // Opening a new activity always supersedes a close for the anim.
2619 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 }
2621 mAppTransitionReady = false;
2622 mAppTransitionTimeout = false;
2623 mStartingIconInTransition = false;
2624 mSkipAppTransitionAnimation = false;
2625 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
2626 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
2627 5000);
2628 }
2629 }
2630 }
2631
2632 public int getPendingAppTransition() {
2633 return mNextAppTransition;
2634 }
Romain Guy06882f82009-06-10 13:36:04 -07002635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 public void executeAppTransition() {
2637 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2638 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002639 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 }
Romain Guy06882f82009-06-10 13:36:04 -07002641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 synchronized(mWindowMap) {
2643 if (DEBUG_APP_TRANSITIONS) Log.v(
2644 TAG, "Execute app transition: mNextAppTransition=" + mNextAppTransition);
2645 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
2646 mAppTransitionReady = true;
2647 final long origId = Binder.clearCallingIdentity();
2648 performLayoutAndPlaceSurfacesLocked();
2649 Binder.restoreCallingIdentity(origId);
2650 }
2651 }
2652 }
2653
2654 public void setAppStartingWindow(IBinder token, String pkg,
2655 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
2656 IBinder transferFrom, boolean createIfNeeded) {
2657 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2658 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002659 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 }
2661
2662 synchronized(mWindowMap) {
2663 if (DEBUG_STARTING_WINDOW) Log.v(
2664 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
2665 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07002666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 AppWindowToken wtoken = findAppWindowToken(token);
2668 if (wtoken == null) {
2669 Log.w(TAG, "Attempted to set icon of non-existing app token: " + token);
2670 return;
2671 }
2672
2673 // If the display is frozen, we won't do anything until the
2674 // actual window is displayed so there is no reason to put in
2675 // the starting window.
2676 if (mDisplayFrozen) {
2677 return;
2678 }
Romain Guy06882f82009-06-10 13:36:04 -07002679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 if (wtoken.startingData != null) {
2681 return;
2682 }
Romain Guy06882f82009-06-10 13:36:04 -07002683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 if (transferFrom != null) {
2685 AppWindowToken ttoken = findAppWindowToken(transferFrom);
2686 if (ttoken != null) {
2687 WindowState startingWindow = ttoken.startingWindow;
2688 if (startingWindow != null) {
2689 if (mStartingIconInTransition) {
2690 // In this case, the starting icon has already
2691 // been displayed, so start letting windows get
2692 // shown immediately without any more transitions.
2693 mSkipAppTransitionAnimation = true;
2694 }
2695 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
2696 "Moving existing starting from " + ttoken
2697 + " to " + wtoken);
2698 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 // Transfer the starting window over to the new
2701 // token.
2702 wtoken.startingData = ttoken.startingData;
2703 wtoken.startingView = ttoken.startingView;
2704 wtoken.startingWindow = startingWindow;
2705 ttoken.startingData = null;
2706 ttoken.startingView = null;
2707 ttoken.startingWindow = null;
2708 ttoken.startingMoved = true;
2709 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07002710 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 startingWindow.mAppToken = wtoken;
2712 mWindows.remove(startingWindow);
2713 ttoken.windows.remove(startingWindow);
2714 ttoken.allAppWindows.remove(startingWindow);
2715 addWindowToListInOrderLocked(startingWindow, true);
2716 wtoken.allAppWindows.add(startingWindow);
Romain Guy06882f82009-06-10 13:36:04 -07002717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002718 // Propagate other interesting state between the
2719 // tokens. If the old token is displayed, we should
2720 // immediately force the new one to be displayed. If
2721 // it is animating, we need to move that animation to
2722 // the new one.
2723 if (ttoken.allDrawn) {
2724 wtoken.allDrawn = true;
2725 }
2726 if (ttoken.firstWindowDrawn) {
2727 wtoken.firstWindowDrawn = true;
2728 }
2729 if (!ttoken.hidden) {
2730 wtoken.hidden = false;
2731 wtoken.hiddenRequested = false;
2732 wtoken.willBeHidden = false;
2733 }
2734 if (wtoken.clientHidden != ttoken.clientHidden) {
2735 wtoken.clientHidden = ttoken.clientHidden;
2736 wtoken.sendAppVisibilityToClients();
2737 }
2738 if (ttoken.animation != null) {
2739 wtoken.animation = ttoken.animation;
2740 wtoken.animating = ttoken.animating;
2741 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
2742 ttoken.animation = null;
2743 ttoken.animLayerAdjustment = 0;
2744 wtoken.updateLayers();
2745 ttoken.updateLayers();
2746 }
Romain Guy06882f82009-06-10 13:36:04 -07002747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 mLayoutNeeded = true;
2750 performLayoutAndPlaceSurfacesLocked();
2751 Binder.restoreCallingIdentity(origId);
2752 return;
2753 } else if (ttoken.startingData != null) {
2754 // The previous app was getting ready to show a
2755 // starting window, but hasn't yet done so. Steal it!
2756 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
2757 "Moving pending starting from " + ttoken
2758 + " to " + wtoken);
2759 wtoken.startingData = ttoken.startingData;
2760 ttoken.startingData = null;
2761 ttoken.startingMoved = true;
2762 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
2763 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2764 // want to process the message ASAP, before any other queued
2765 // messages.
2766 mH.sendMessageAtFrontOfQueue(m);
2767 return;
2768 }
2769 }
2770 }
2771
2772 // There is no existing starting window, and the caller doesn't
2773 // want us to create one, so that's it!
2774 if (!createIfNeeded) {
2775 return;
2776 }
Romain Guy06882f82009-06-10 13:36:04 -07002777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 mStartingIconInTransition = true;
2779 wtoken.startingData = new StartingData(
2780 pkg, theme, nonLocalizedLabel,
2781 labelRes, icon);
2782 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
2783 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2784 // want to process the message ASAP, before any other queued
2785 // messages.
2786 mH.sendMessageAtFrontOfQueue(m);
2787 }
2788 }
2789
2790 public void setAppWillBeHidden(IBinder token) {
2791 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2792 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002793 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 }
2795
2796 AppWindowToken wtoken;
2797
2798 synchronized(mWindowMap) {
2799 wtoken = findAppWindowToken(token);
2800 if (wtoken == null) {
2801 Log.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
2802 return;
2803 }
2804 wtoken.willBeHidden = true;
2805 }
2806 }
Romain Guy06882f82009-06-10 13:36:04 -07002807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
2809 boolean visible, int transit, boolean performLayout) {
2810 boolean delayed = false;
2811
2812 if (wtoken.clientHidden == visible) {
2813 wtoken.clientHidden = !visible;
2814 wtoken.sendAppVisibilityToClients();
2815 }
Romain Guy06882f82009-06-10 13:36:04 -07002816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 wtoken.willBeHidden = false;
2818 if (wtoken.hidden == visible) {
2819 final int N = wtoken.allAppWindows.size();
2820 boolean changed = false;
2821 if (DEBUG_APP_TRANSITIONS) Log.v(
2822 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
2823 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07002824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07002826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 if (transit != WindowManagerPolicy.TRANSIT_NONE) {
2828 if (wtoken.animation == sDummyAnimation) {
2829 wtoken.animation = null;
2830 }
2831 applyAnimationLocked(wtoken, lp, transit, visible);
2832 changed = true;
2833 if (wtoken.animation != null) {
2834 delayed = runningAppAnimation = true;
2835 }
2836 }
Romain Guy06882f82009-06-10 13:36:04 -07002837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 for (int i=0; i<N; i++) {
2839 WindowState win = wtoken.allAppWindows.get(i);
2840 if (win == wtoken.startingWindow) {
2841 continue;
2842 }
2843
2844 if (win.isAnimating()) {
2845 delayed = true;
2846 }
Romain Guy06882f82009-06-10 13:36:04 -07002847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 //Log.i(TAG, "Window " + win + ": vis=" + win.isVisible());
2849 //win.dump(" ");
2850 if (visible) {
2851 if (!win.isVisibleNow()) {
2852 if (!runningAppAnimation) {
2853 applyAnimationLocked(win,
2854 WindowManagerPolicy.TRANSIT_ENTER, true);
2855 }
2856 changed = true;
2857 }
2858 } else if (win.isVisibleNow()) {
2859 if (!runningAppAnimation) {
2860 applyAnimationLocked(win,
2861 WindowManagerPolicy.TRANSIT_EXIT, false);
2862 }
2863 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2864 KeyWaiter.RETURN_NOTHING);
2865 changed = true;
2866 }
2867 }
2868
2869 wtoken.hidden = wtoken.hiddenRequested = !visible;
2870 if (!visible) {
2871 unsetAppFreezingScreenLocked(wtoken, true, true);
2872 } else {
2873 // If we are being set visible, and the starting window is
2874 // not yet displayed, then make sure it doesn't get displayed.
2875 WindowState swin = wtoken.startingWindow;
2876 if (swin != null && (swin.mDrawPending
2877 || swin.mCommitDrawPending)) {
2878 swin.mPolicyVisibility = false;
2879 swin.mPolicyVisibilityAfterAnim = false;
2880 }
2881 }
Romain Guy06882f82009-06-10 13:36:04 -07002882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "setTokenVisibilityLocked: " + wtoken
2884 + ": hidden=" + wtoken.hidden + " hiddenRequested="
2885 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07002886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 if (changed && performLayout) {
2888 mLayoutNeeded = true;
2889 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 performLayoutAndPlaceSurfacesLocked();
2891 }
2892 }
2893
2894 if (wtoken.animation != null) {
2895 delayed = true;
2896 }
Romain Guy06882f82009-06-10 13:36:04 -07002897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 return delayed;
2899 }
2900
2901 public void setAppVisibility(IBinder token, boolean visible) {
2902 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2903 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002904 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 }
2906
2907 AppWindowToken wtoken;
2908
2909 synchronized(mWindowMap) {
2910 wtoken = findAppWindowToken(token);
2911 if (wtoken == null) {
2912 Log.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
2913 return;
2914 }
2915
2916 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
2917 RuntimeException e = new RuntimeException();
2918 e.fillInStackTrace();
2919 Log.v(TAG, "setAppVisibility(" + token + ", " + visible
2920 + "): mNextAppTransition=" + mNextAppTransition
2921 + " hidden=" + wtoken.hidden
2922 + " hiddenRequested=" + wtoken.hiddenRequested, e);
2923 }
Romain Guy06882f82009-06-10 13:36:04 -07002924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 // If we are preparing an app transition, then delay changing
2926 // the visibility of this token until we execute that transition.
2927 if (!mDisplayFrozen && mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
2928 // Already in requested state, don't do anything more.
2929 if (wtoken.hiddenRequested != visible) {
2930 return;
2931 }
2932 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07002933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 if (DEBUG_APP_TRANSITIONS) Log.v(
2935 TAG, "Setting dummy animation on: " + wtoken);
2936 wtoken.setDummyAnimation();
2937 mOpeningApps.remove(wtoken);
2938 mClosingApps.remove(wtoken);
2939 wtoken.inPendingTransaction = true;
2940 if (visible) {
2941 mOpeningApps.add(wtoken);
2942 wtoken.allDrawn = false;
2943 wtoken.startingDisplayed = false;
2944 wtoken.startingMoved = false;
Romain Guy06882f82009-06-10 13:36:04 -07002945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 if (wtoken.clientHidden) {
2947 // In the case where we are making an app visible
2948 // but holding off for a transition, we still need
2949 // to tell the client to make its windows visible so
2950 // they get drawn. Otherwise, we will wait on
2951 // performing the transition until all windows have
2952 // been drawn, they never will be, and we are sad.
2953 wtoken.clientHidden = false;
2954 wtoken.sendAppVisibilityToClients();
2955 }
2956 } else {
2957 mClosingApps.add(wtoken);
2958 }
2959 return;
2960 }
Romain Guy06882f82009-06-10 13:36:04 -07002961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 final long origId = Binder.clearCallingIdentity();
2963 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_NONE, true);
2964 wtoken.updateReportedVisibilityLocked();
2965 Binder.restoreCallingIdentity(origId);
2966 }
2967 }
2968
2969 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
2970 boolean unfreezeSurfaceNow, boolean force) {
2971 if (wtoken.freezingScreen) {
2972 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + wtoken
2973 + " force=" + force);
2974 final int N = wtoken.allAppWindows.size();
2975 boolean unfrozeWindows = false;
2976 for (int i=0; i<N; i++) {
2977 WindowState w = wtoken.allAppWindows.get(i);
2978 if (w.mAppFreezing) {
2979 w.mAppFreezing = false;
2980 if (w.mSurface != null && !w.mOrientationChanging) {
2981 w.mOrientationChanging = true;
2982 }
2983 unfrozeWindows = true;
2984 }
2985 }
2986 if (force || unfrozeWindows) {
2987 if (DEBUG_ORIENTATION) Log.v(TAG, "No longer freezing: " + wtoken);
2988 wtoken.freezingScreen = false;
2989 mAppsFreezingScreen--;
2990 }
2991 if (unfreezeSurfaceNow) {
2992 if (unfrozeWindows) {
2993 mLayoutNeeded = true;
2994 performLayoutAndPlaceSurfacesLocked();
2995 }
2996 if (mAppsFreezingScreen == 0 && !mWindowsFreezingScreen) {
2997 stopFreezingDisplayLocked();
2998 }
2999 }
3000 }
3001 }
Romain Guy06882f82009-06-10 13:36:04 -07003002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3004 int configChanges) {
3005 if (DEBUG_ORIENTATION) {
3006 RuntimeException e = new RuntimeException();
3007 e.fillInStackTrace();
3008 Log.i(TAG, "Set freezing of " + wtoken.appToken
3009 + ": hidden=" + wtoken.hidden + " freezing="
3010 + wtoken.freezingScreen, e);
3011 }
3012 if (!wtoken.hiddenRequested) {
3013 if (!wtoken.freezingScreen) {
3014 wtoken.freezingScreen = true;
3015 mAppsFreezingScreen++;
3016 if (mAppsFreezingScreen == 1) {
3017 startFreezingDisplayLocked();
3018 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3019 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3020 5000);
3021 }
3022 }
3023 final int N = wtoken.allAppWindows.size();
3024 for (int i=0; i<N; i++) {
3025 WindowState w = wtoken.allAppWindows.get(i);
3026 w.mAppFreezing = true;
3027 }
3028 }
3029 }
Romain Guy06882f82009-06-10 13:36:04 -07003030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 public void startAppFreezingScreen(IBinder token, int configChanges) {
3032 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3033 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003034 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003035 }
3036
3037 synchronized(mWindowMap) {
3038 if (configChanges == 0 && !mDisplayFrozen) {
3039 if (DEBUG_ORIENTATION) Log.v(TAG, "Skipping set freeze of " + token);
3040 return;
3041 }
Romain Guy06882f82009-06-10 13:36:04 -07003042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 AppWindowToken wtoken = findAppWindowToken(token);
3044 if (wtoken == null || wtoken.appToken == null) {
3045 Log.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
3046 return;
3047 }
3048 final long origId = Binder.clearCallingIdentity();
3049 startAppFreezingScreenLocked(wtoken, configChanges);
3050 Binder.restoreCallingIdentity(origId);
3051 }
3052 }
Romain Guy06882f82009-06-10 13:36:04 -07003053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 public void stopAppFreezingScreen(IBinder token, boolean force) {
3055 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3056 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003057 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 }
3059
3060 synchronized(mWindowMap) {
3061 AppWindowToken wtoken = findAppWindowToken(token);
3062 if (wtoken == null || wtoken.appToken == null) {
3063 return;
3064 }
3065 final long origId = Binder.clearCallingIdentity();
3066 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + token
3067 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3068 unsetAppFreezingScreenLocked(wtoken, true, force);
3069 Binder.restoreCallingIdentity(origId);
3070 }
3071 }
Romain Guy06882f82009-06-10 13:36:04 -07003072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 public void removeAppToken(IBinder token) {
3074 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3075 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003076 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 }
3078
3079 AppWindowToken wtoken = null;
3080 AppWindowToken startingToken = null;
3081 boolean delayed = false;
3082
3083 final long origId = Binder.clearCallingIdentity();
3084 synchronized(mWindowMap) {
3085 WindowToken basewtoken = mTokenMap.remove(token);
3086 mTokenList.remove(basewtoken);
3087 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
3088 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "Removing app token: " + wtoken);
3089 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_NONE, true);
3090 wtoken.inPendingTransaction = false;
3091 mOpeningApps.remove(wtoken);
3092 if (mClosingApps.contains(wtoken)) {
3093 delayed = true;
3094 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
3095 mClosingApps.add(wtoken);
3096 delayed = true;
3097 }
3098 if (DEBUG_APP_TRANSITIONS) Log.v(
3099 TAG, "Removing app " + wtoken + " delayed=" + delayed
3100 + " animation=" + wtoken.animation
3101 + " animating=" + wtoken.animating);
3102 if (delayed) {
3103 // set the token aside because it has an active animation to be finished
3104 mExitingAppTokens.add(wtoken);
3105 }
3106 mAppTokens.remove(wtoken);
3107 wtoken.removed = true;
3108 if (wtoken.startingData != null) {
3109 startingToken = wtoken;
3110 }
3111 unsetAppFreezingScreenLocked(wtoken, true, true);
3112 if (mFocusedApp == wtoken) {
3113 if (DEBUG_FOCUS) Log.v(TAG, "Removing focused app token:" + wtoken);
3114 mFocusedApp = null;
3115 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3116 mKeyWaiter.tickle();
3117 }
3118 } else {
3119 Log.w(TAG, "Attempted to remove non-existing app token: " + token);
3120 }
Romain Guy06882f82009-06-10 13:36:04 -07003121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 if (!delayed && wtoken != null) {
3123 wtoken.updateReportedVisibilityLocked();
3124 }
3125 }
3126 Binder.restoreCallingIdentity(origId);
3127
3128 if (startingToken != null) {
3129 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Schedule remove starting "
3130 + startingToken + ": app token removed");
3131 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3132 mH.sendMessage(m);
3133 }
3134 }
3135
3136 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3137 final int NW = token.windows.size();
3138 for (int i=0; i<NW; i++) {
3139 WindowState win = token.windows.get(i);
3140 mWindows.remove(win);
3141 int j = win.mChildWindows.size();
3142 while (j > 0) {
3143 j--;
3144 mWindows.remove(win.mChildWindows.get(j));
3145 }
3146 }
3147 return NW > 0;
3148 }
3149
3150 void dumpAppTokensLocked() {
3151 for (int i=mAppTokens.size()-1; i>=0; i--) {
3152 Log.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
3153 }
3154 }
Romain Guy06882f82009-06-10 13:36:04 -07003155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003156 void dumpWindowsLocked() {
3157 for (int i=mWindows.size()-1; i>=0; i--) {
3158 Log.v(TAG, " #" + i + ": " + mWindows.get(i));
3159 }
3160 }
Romain Guy06882f82009-06-10 13:36:04 -07003161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 private int findWindowOffsetLocked(int tokenPos) {
3163 final int NW = mWindows.size();
3164
3165 if (tokenPos >= mAppTokens.size()) {
3166 int i = NW;
3167 while (i > 0) {
3168 i--;
3169 WindowState win = (WindowState)mWindows.get(i);
3170 if (win.getAppToken() != null) {
3171 return i+1;
3172 }
3173 }
3174 }
3175
3176 while (tokenPos > 0) {
3177 // Find the first app token below the new position that has
3178 // a window displayed.
3179 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
3180 if (DEBUG_REORDER) Log.v(TAG, "Looking for lower windows @ "
3181 + tokenPos + " -- " + wtoken.token);
3182 int i = wtoken.windows.size();
3183 while (i > 0) {
3184 i--;
3185 WindowState win = wtoken.windows.get(i);
3186 int j = win.mChildWindows.size();
3187 while (j > 0) {
3188 j--;
3189 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3190 if (cwin.mSubLayer >= 0 ) {
3191 for (int pos=NW-1; pos>=0; pos--) {
3192 if (mWindows.get(pos) == cwin) {
3193 if (DEBUG_REORDER) Log.v(TAG,
3194 "Found child win @" + (pos+1));
3195 return pos+1;
3196 }
3197 }
3198 }
3199 }
3200 for (int pos=NW-1; pos>=0; pos--) {
3201 if (mWindows.get(pos) == win) {
3202 if (DEBUG_REORDER) Log.v(TAG, "Found win @" + (pos+1));
3203 return pos+1;
3204 }
3205 }
3206 }
3207 tokenPos--;
3208 }
3209
3210 return 0;
3211 }
3212
3213 private final int reAddWindowLocked(int index, WindowState win) {
3214 final int NCW = win.mChildWindows.size();
3215 boolean added = false;
3216 for (int j=0; j<NCW; j++) {
3217 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3218 if (!added && cwin.mSubLayer >= 0) {
3219 mWindows.add(index, win);
3220 index++;
3221 added = true;
3222 }
3223 mWindows.add(index, cwin);
3224 index++;
3225 }
3226 if (!added) {
3227 mWindows.add(index, win);
3228 index++;
3229 }
3230 return index;
3231 }
Romain Guy06882f82009-06-10 13:36:04 -07003232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 private final int reAddAppWindowsLocked(int index, WindowToken token) {
3234 final int NW = token.windows.size();
3235 for (int i=0; i<NW; i++) {
3236 index = reAddWindowLocked(index, token.windows.get(i));
3237 }
3238 return index;
3239 }
3240
3241 public void moveAppToken(int index, IBinder token) {
3242 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3243 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003244 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 }
3246
3247 synchronized(mWindowMap) {
3248 if (DEBUG_REORDER) Log.v(TAG, "Initial app tokens:");
3249 if (DEBUG_REORDER) dumpAppTokensLocked();
3250 final AppWindowToken wtoken = findAppWindowToken(token);
3251 if (wtoken == null || !mAppTokens.remove(wtoken)) {
3252 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
3253 + token + " (" + wtoken + ")");
3254 return;
3255 }
3256 mAppTokens.add(index, wtoken);
3257 if (DEBUG_REORDER) Log.v(TAG, "Moved " + token + " to " + index + ":");
3258 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 final long origId = Binder.clearCallingIdentity();
3261 if (DEBUG_REORDER) Log.v(TAG, "Removing windows in " + token + ":");
3262 if (DEBUG_REORDER) dumpWindowsLocked();
3263 if (tmpRemoveAppWindowsLocked(wtoken)) {
3264 if (DEBUG_REORDER) Log.v(TAG, "Adding windows back in:");
3265 if (DEBUG_REORDER) dumpWindowsLocked();
3266 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
3267 if (DEBUG_REORDER) Log.v(TAG, "Final window list:");
3268 if (DEBUG_REORDER) dumpWindowsLocked();
3269 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 mLayoutNeeded = true;
3271 performLayoutAndPlaceSurfacesLocked();
3272 }
3273 Binder.restoreCallingIdentity(origId);
3274 }
3275 }
3276
3277 private void removeAppTokensLocked(List<IBinder> tokens) {
3278 // XXX This should be done more efficiently!
3279 // (take advantage of the fact that both lists should be
3280 // ordered in the same way.)
3281 int N = tokens.size();
3282 for (int i=0; i<N; i++) {
3283 IBinder token = tokens.get(i);
3284 final AppWindowToken wtoken = findAppWindowToken(token);
3285 if (!mAppTokens.remove(wtoken)) {
3286 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
3287 + token + " (" + wtoken + ")");
3288 i--;
3289 N--;
3290 }
3291 }
3292 }
3293
3294 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
3295 // First remove all of the windows from the list.
3296 final int N = tokens.size();
3297 int i;
3298 for (i=0; i<N; i++) {
3299 WindowToken token = mTokenMap.get(tokens.get(i));
3300 if (token != null) {
3301 tmpRemoveAppWindowsLocked(token);
3302 }
3303 }
3304
3305 // Where to start adding?
3306 int pos = findWindowOffsetLocked(tokenPos);
3307
3308 // And now add them back at the correct place.
3309 for (i=0; i<N; i++) {
3310 WindowToken token = mTokenMap.get(tokens.get(i));
3311 if (token != null) {
3312 pos = reAddAppWindowsLocked(pos, token);
3313 }
3314 }
3315
3316 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 mLayoutNeeded = true;
3318 performLayoutAndPlaceSurfacesLocked();
3319
3320 //dump();
3321 }
3322
3323 public void moveAppTokensToTop(List<IBinder> tokens) {
3324 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3325 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003326 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 }
3328
3329 final long origId = Binder.clearCallingIdentity();
3330 synchronized(mWindowMap) {
3331 removeAppTokensLocked(tokens);
3332 final int N = tokens.size();
3333 for (int i=0; i<N; i++) {
3334 AppWindowToken wt = findAppWindowToken(tokens.get(i));
3335 if (wt != null) {
3336 mAppTokens.add(wt);
3337 }
3338 }
3339 moveAppWindowsLocked(tokens, mAppTokens.size());
3340 }
3341 Binder.restoreCallingIdentity(origId);
3342 }
3343
3344 public void moveAppTokensToBottom(List<IBinder> tokens) {
3345 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3346 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003347 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 }
3349
3350 final long origId = Binder.clearCallingIdentity();
3351 synchronized(mWindowMap) {
3352 removeAppTokensLocked(tokens);
3353 final int N = tokens.size();
3354 int pos = 0;
3355 for (int i=0; i<N; i++) {
3356 AppWindowToken wt = findAppWindowToken(tokens.get(i));
3357 if (wt != null) {
3358 mAppTokens.add(pos, wt);
3359 pos++;
3360 }
3361 }
3362 moveAppWindowsLocked(tokens, 0);
3363 }
3364 Binder.restoreCallingIdentity(origId);
3365 }
3366
3367 // -------------------------------------------------------------
3368 // Misc IWindowSession methods
3369 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07003370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 public void disableKeyguard(IBinder token, String tag) {
3372 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3373 != PackageManager.PERMISSION_GRANTED) {
3374 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3375 }
3376 mKeyguardDisabled.acquire(token, tag);
3377 }
3378
3379 public void reenableKeyguard(IBinder token) {
3380 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3381 != PackageManager.PERMISSION_GRANTED) {
3382 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3383 }
3384 synchronized (mKeyguardDisabled) {
3385 mKeyguardDisabled.release(token);
3386
3387 if (!mKeyguardDisabled.isAcquired()) {
3388 // if we are the last one to reenable the keyguard wait until
3389 // we have actaully finished reenabling until returning
3390 mWaitingUntilKeyguardReenabled = true;
3391 while (mWaitingUntilKeyguardReenabled) {
3392 try {
3393 mKeyguardDisabled.wait();
3394 } catch (InterruptedException e) {
3395 Thread.currentThread().interrupt();
3396 }
3397 }
3398 }
3399 }
3400 }
3401
3402 /**
3403 * @see android.app.KeyguardManager#exitKeyguardSecurely
3404 */
3405 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
3406 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3407 != PackageManager.PERMISSION_GRANTED) {
3408 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3409 }
3410 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
3411 public void onKeyguardExitResult(boolean success) {
3412 try {
3413 callback.onKeyguardExitResult(success);
3414 } catch (RemoteException e) {
3415 // Client has died, we don't care.
3416 }
3417 }
3418 });
3419 }
3420
3421 public boolean inKeyguardRestrictedInputMode() {
3422 return mPolicy.inKeyguardRestrictedKeyInputMode();
3423 }
Romain Guy06882f82009-06-10 13:36:04 -07003424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 static float fixScale(float scale) {
3426 if (scale < 0) scale = 0;
3427 else if (scale > 20) scale = 20;
3428 return Math.abs(scale);
3429 }
Romain Guy06882f82009-06-10 13:36:04 -07003430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 public void setAnimationScale(int which, float scale) {
3432 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3433 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003434 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 }
3436
3437 if (scale < 0) scale = 0;
3438 else if (scale > 20) scale = 20;
3439 scale = Math.abs(scale);
3440 switch (which) {
3441 case 0: mWindowAnimationScale = fixScale(scale); break;
3442 case 1: mTransitionAnimationScale = fixScale(scale); break;
3443 }
Romain Guy06882f82009-06-10 13:36:04 -07003444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 // Persist setting
3446 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
3447 }
Romain Guy06882f82009-06-10 13:36:04 -07003448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 public void setAnimationScales(float[] scales) {
3450 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3451 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003452 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
3454
3455 if (scales != null) {
3456 if (scales.length >= 1) {
3457 mWindowAnimationScale = fixScale(scales[0]);
3458 }
3459 if (scales.length >= 2) {
3460 mTransitionAnimationScale = fixScale(scales[1]);
3461 }
3462 }
Romain Guy06882f82009-06-10 13:36:04 -07003463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 // Persist setting
3465 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
3466 }
Romain Guy06882f82009-06-10 13:36:04 -07003467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 public float getAnimationScale(int which) {
3469 switch (which) {
3470 case 0: return mWindowAnimationScale;
3471 case 1: return mTransitionAnimationScale;
3472 }
3473 return 0;
3474 }
Romain Guy06882f82009-06-10 13:36:04 -07003475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 public float[] getAnimationScales() {
3477 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
3478 }
Romain Guy06882f82009-06-10 13:36:04 -07003479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 public int getSwitchState(int sw) {
3481 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3482 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003483 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 }
3485 return KeyInputQueue.getSwitchState(sw);
3486 }
Romain Guy06882f82009-06-10 13:36:04 -07003487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 public int getSwitchStateForDevice(int devid, int sw) {
3489 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3490 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003491 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 }
3493 return KeyInputQueue.getSwitchState(devid, sw);
3494 }
Romain Guy06882f82009-06-10 13:36:04 -07003495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 public int getScancodeState(int sw) {
3497 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3498 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003499 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 }
3501 return KeyInputQueue.getScancodeState(sw);
3502 }
Romain Guy06882f82009-06-10 13:36:04 -07003503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 public int getScancodeStateForDevice(int devid, int sw) {
3505 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3506 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003507 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 }
3509 return KeyInputQueue.getScancodeState(devid, sw);
3510 }
Romain Guy06882f82009-06-10 13:36:04 -07003511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 public int getKeycodeState(int sw) {
3513 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3514 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003515 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 }
3517 return KeyInputQueue.getKeycodeState(sw);
3518 }
Romain Guy06882f82009-06-10 13:36:04 -07003519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 public int getKeycodeStateForDevice(int devid, int sw) {
3521 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3522 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003523 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 }
3525 return KeyInputQueue.getKeycodeState(devid, sw);
3526 }
Romain Guy06882f82009-06-10 13:36:04 -07003527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
3529 return KeyInputQueue.hasKeys(keycodes, keyExists);
3530 }
Romain Guy06882f82009-06-10 13:36:04 -07003531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 public void enableScreenAfterBoot() {
3533 synchronized(mWindowMap) {
3534 if (mSystemBooted) {
3535 return;
3536 }
3537 mSystemBooted = true;
3538 }
Romain Guy06882f82009-06-10 13:36:04 -07003539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 performEnableScreen();
3541 }
Romain Guy06882f82009-06-10 13:36:04 -07003542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 public void enableScreenIfNeededLocked() {
3544 if (mDisplayEnabled) {
3545 return;
3546 }
3547 if (!mSystemBooted) {
3548 return;
3549 }
3550 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
3551 }
Romain Guy06882f82009-06-10 13:36:04 -07003552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553 public void performEnableScreen() {
3554 synchronized(mWindowMap) {
3555 if (mDisplayEnabled) {
3556 return;
3557 }
3558 if (!mSystemBooted) {
3559 return;
3560 }
Romain Guy06882f82009-06-10 13:36:04 -07003561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 // Don't enable the screen until all existing windows
3563 // have been drawn.
3564 final int N = mWindows.size();
3565 for (int i=0; i<N; i++) {
3566 WindowState w = (WindowState)mWindows.get(i);
3567 if (w.isVisibleLw() && !w.isDisplayedLw()) {
3568 return;
3569 }
3570 }
Romain Guy06882f82009-06-10 13:36:04 -07003571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 mDisplayEnabled = true;
3573 if (false) {
3574 Log.i(TAG, "ENABLING SCREEN!");
3575 StringWriter sw = new StringWriter();
3576 PrintWriter pw = new PrintWriter(sw);
3577 this.dump(null, pw, null);
3578 Log.i(TAG, sw.toString());
3579 }
3580 try {
3581 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
3582 if (surfaceFlinger != null) {
3583 //Log.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
3584 Parcel data = Parcel.obtain();
3585 data.writeInterfaceToken("android.ui.ISurfaceComposer");
3586 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
3587 data, null, 0);
3588 data.recycle();
3589 }
3590 } catch (RemoteException ex) {
3591 Log.e(TAG, "Boot completed: SurfaceFlinger is dead!");
3592 }
3593 }
Romain Guy06882f82009-06-10 13:36:04 -07003594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07003596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07003598 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
3599 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 }
Romain Guy06882f82009-06-10 13:36:04 -07003601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003602 public void setInTouchMode(boolean mode) {
3603 synchronized(mWindowMap) {
3604 mInTouchMode = mode;
3605 }
3606 }
3607
Romain Guy06882f82009-06-10 13:36:04 -07003608 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003609 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003611 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003612 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 }
3614
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003615 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 }
Romain Guy06882f82009-06-10 13:36:04 -07003617
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003618 public void setRotationUnchecked(int rotation,
3619 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 if(DEBUG_ORIENTATION) Log.v(TAG,
3621 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07003622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 long origId = Binder.clearCallingIdentity();
3624 boolean changed;
3625 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003626 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 }
Romain Guy06882f82009-06-10 13:36:04 -07003628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 if (changed) {
3630 sendNewConfiguration();
3631 synchronized(mWindowMap) {
3632 mLayoutNeeded = true;
3633 performLayoutAndPlaceSurfacesLocked();
3634 }
3635 } else if (alwaysSendConfiguration) {
3636 //update configuration ignoring orientation change
3637 sendNewConfiguration();
3638 }
Romain Guy06882f82009-06-10 13:36:04 -07003639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003640 Binder.restoreCallingIdentity(origId);
3641 }
Romain Guy06882f82009-06-10 13:36:04 -07003642
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003643 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 boolean changed;
3645 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
3646 rotation = mRequestedRotation;
3647 } else {
3648 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07003649 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 }
3651 if (DEBUG_ORIENTATION) Log.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003652 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 mRotation, mDisplayEnabled);
3654 if (DEBUG_ORIENTATION) Log.v(TAG, "new rotation is set to " + rotation);
3655 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07003656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 if (changed) {
Romain Guy06882f82009-06-10 13:36:04 -07003658 if (DEBUG_ORIENTATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 "Rotation changed to " + rotation
3660 + " from " + mRotation
3661 + " (forceApp=" + mForcedAppOrientation
3662 + ", req=" + mRequestedRotation + ")");
3663 mRotation = rotation;
3664 mWindowsFreezingScreen = true;
3665 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
3666 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
3667 2000);
3668 startFreezingDisplayLocked();
Dianne Hackborn1e880db2009-03-27 16:04:08 -07003669 Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 mQueue.setOrientation(rotation);
3671 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07003672 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 }
3674 for (int i=mWindows.size()-1; i>=0; i--) {
3675 WindowState w = (WindowState)mWindows.get(i);
3676 if (w.mSurface != null) {
3677 w.mOrientationChanging = true;
3678 }
3679 }
3680 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
3681 try {
3682 mRotationWatchers.get(i).onRotationChanged(rotation);
3683 } catch (RemoteException e) {
3684 }
3685 }
3686 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07003687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 return changed;
3689 }
Romain Guy06882f82009-06-10 13:36:04 -07003690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 public int getRotation() {
3692 return mRotation;
3693 }
3694
3695 public int watchRotation(IRotationWatcher watcher) {
3696 final IBinder watcherBinder = watcher.asBinder();
3697 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
3698 public void binderDied() {
3699 synchronized (mWindowMap) {
3700 for (int i=0; i<mRotationWatchers.size(); i++) {
3701 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07003702 IRotationWatcher removed = mRotationWatchers.remove(i);
3703 if (removed != null) {
3704 removed.asBinder().unlinkToDeath(this, 0);
3705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 i--;
3707 }
3708 }
3709 }
3710 }
3711 };
Romain Guy06882f82009-06-10 13:36:04 -07003712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 synchronized (mWindowMap) {
3714 try {
3715 watcher.asBinder().linkToDeath(dr, 0);
3716 mRotationWatchers.add(watcher);
3717 } catch (RemoteException e) {
3718 // Client died, no cleanup needed.
3719 }
Romain Guy06882f82009-06-10 13:36:04 -07003720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 return mRotation;
3722 }
3723 }
3724
3725 /**
3726 * Starts the view server on the specified port.
3727 *
3728 * @param port The port to listener to.
3729 *
3730 * @return True if the server was successfully started, false otherwise.
3731 *
3732 * @see com.android.server.ViewServer
3733 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
3734 */
3735 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07003736 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 return false;
3738 }
3739
3740 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
3741 return false;
3742 }
3743
3744 if (port < 1024) {
3745 return false;
3746 }
3747
3748 if (mViewServer != null) {
3749 if (!mViewServer.isRunning()) {
3750 try {
3751 return mViewServer.start();
3752 } catch (IOException e) {
Romain Guy06882f82009-06-10 13:36:04 -07003753 Log.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 }
3755 }
3756 return false;
3757 }
3758
3759 try {
3760 mViewServer = new ViewServer(this, port);
3761 return mViewServer.start();
3762 } catch (IOException e) {
3763 Log.w(TAG, "View server did not start");
3764 }
3765 return false;
3766 }
3767
Romain Guy06882f82009-06-10 13:36:04 -07003768 private boolean isSystemSecure() {
3769 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
3770 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
3771 }
3772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 /**
3774 * Stops the view server if it exists.
3775 *
3776 * @return True if the server stopped, false if it wasn't started or
3777 * couldn't be stopped.
3778 *
3779 * @see com.android.server.ViewServer
3780 */
3781 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07003782 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 return false;
3784 }
3785
3786 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
3787 return false;
3788 }
3789
3790 if (mViewServer != null) {
3791 return mViewServer.stop();
3792 }
3793 return false;
3794 }
3795
3796 /**
3797 * Indicates whether the view server is running.
3798 *
3799 * @return True if the server is running, false otherwise.
3800 *
3801 * @see com.android.server.ViewServer
3802 */
3803 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07003804 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 return false;
3806 }
3807
3808 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
3809 return false;
3810 }
3811
3812 return mViewServer != null && mViewServer.isRunning();
3813 }
3814
3815 /**
3816 * Lists all availble windows in the system. The listing is written in the
3817 * specified Socket's output stream with the following syntax:
3818 * windowHashCodeInHexadecimal windowName
3819 * Each line of the ouput represents a different window.
3820 *
3821 * @param client The remote client to send the listing to.
3822 * @return False if an error occured, true otherwise.
3823 */
3824 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07003825 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 return false;
3827 }
3828
3829 boolean result = true;
3830
3831 Object[] windows;
3832 synchronized (mWindowMap) {
3833 windows = new Object[mWindows.size()];
3834 //noinspection unchecked
3835 windows = mWindows.toArray(windows);
3836 }
3837
3838 BufferedWriter out = null;
3839
3840 // Any uncaught exception will crash the system process
3841 try {
3842 OutputStream clientStream = client.getOutputStream();
3843 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
3844
3845 final int count = windows.length;
3846 for (int i = 0; i < count; i++) {
3847 final WindowState w = (WindowState) windows[i];
3848 out.write(Integer.toHexString(System.identityHashCode(w)));
3849 out.write(' ');
3850 out.append(w.mAttrs.getTitle());
3851 out.write('\n');
3852 }
3853
3854 out.write("DONE.\n");
3855 out.flush();
3856 } catch (Exception e) {
3857 result = false;
3858 } finally {
3859 if (out != null) {
3860 try {
3861 out.close();
3862 } catch (IOException e) {
3863 result = false;
3864 }
3865 }
3866 }
3867
3868 return result;
3869 }
3870
3871 /**
3872 * Sends a command to a target window. The result of the command, if any, will be
3873 * written in the output stream of the specified socket.
3874 *
3875 * The parameters must follow this syntax:
3876 * windowHashcode extra
3877 *
3878 * Where XX is the length in characeters of the windowTitle.
3879 *
3880 * The first parameter is the target window. The window with the specified hashcode
3881 * will be the target. If no target can be found, nothing happens. The extra parameters
3882 * will be delivered to the target window and as parameters to the command itself.
3883 *
3884 * @param client The remote client to sent the result, if any, to.
3885 * @param command The command to execute.
3886 * @param parameters The command parameters.
3887 *
3888 * @return True if the command was successfully delivered, false otherwise. This does
3889 * not indicate whether the command itself was successful.
3890 */
3891 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07003892 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 return false;
3894 }
3895
3896 boolean success = true;
3897 Parcel data = null;
3898 Parcel reply = null;
3899
3900 // Any uncaught exception will crash the system process
3901 try {
3902 // Find the hashcode of the window
3903 int index = parameters.indexOf(' ');
3904 if (index == -1) {
3905 index = parameters.length();
3906 }
3907 final String code = parameters.substring(0, index);
3908 int hashCode = "ffffffff".equals(code) ? -1 : Integer.parseInt(code, 16);
3909
3910 // Extract the command's parameter after the window description
3911 if (index < parameters.length()) {
3912 parameters = parameters.substring(index + 1);
3913 } else {
3914 parameters = "";
3915 }
3916
3917 final WindowManagerService.WindowState window = findWindow(hashCode);
3918 if (window == null) {
3919 return false;
3920 }
3921
3922 data = Parcel.obtain();
3923 data.writeInterfaceToken("android.view.IWindow");
3924 data.writeString(command);
3925 data.writeString(parameters);
3926 data.writeInt(1);
3927 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
3928
3929 reply = Parcel.obtain();
3930
3931 final IBinder binder = window.mClient.asBinder();
3932 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
3933 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
3934
3935 reply.readException();
3936
3937 } catch (Exception e) {
3938 Log.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
3939 success = false;
3940 } finally {
3941 if (data != null) {
3942 data.recycle();
3943 }
3944 if (reply != null) {
3945 reply.recycle();
3946 }
3947 }
3948
3949 return success;
3950 }
3951
3952 private WindowState findWindow(int hashCode) {
3953 if (hashCode == -1) {
3954 return getFocusedWindow();
3955 }
3956
3957 synchronized (mWindowMap) {
3958 final ArrayList windows = mWindows;
3959 final int count = windows.size();
3960
3961 for (int i = 0; i < count; i++) {
3962 WindowState w = (WindowState) windows.get(i);
3963 if (System.identityHashCode(w) == hashCode) {
3964 return w;
3965 }
3966 }
3967 }
3968
3969 return null;
3970 }
3971
3972 /*
3973 * Instruct the Activity Manager to fetch the current configuration and broadcast
3974 * that to config-changed listeners if appropriate.
3975 */
3976 void sendNewConfiguration() {
3977 try {
3978 mActivityManager.updateConfiguration(null);
3979 } catch (RemoteException e) {
3980 }
3981 }
Romain Guy06882f82009-06-10 13:36:04 -07003982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 public Configuration computeNewConfiguration() {
3984 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07003985 return computeNewConfigurationLocked();
3986 }
3987 }
Romain Guy06882f82009-06-10 13:36:04 -07003988
Dianne Hackbornc485a602009-03-24 22:39:49 -07003989 Configuration computeNewConfigurationLocked() {
3990 Configuration config = new Configuration();
3991 if (!computeNewConfigurationLocked(config)) {
3992 return null;
3993 }
3994 Log.i(TAG, "Config changed: " + config);
3995 long now = SystemClock.uptimeMillis();
3996 //Log.i(TAG, "Config changing, gc pending: " + mFreezeGcPending + ", now " + now);
3997 if (mFreezeGcPending != 0) {
3998 if (now > (mFreezeGcPending+1000)) {
3999 //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
4000 mH.removeMessages(H.FORCE_GC);
4001 Runtime.getRuntime().gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 mFreezeGcPending = now;
4003 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004004 } else {
4005 mFreezeGcPending = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004007 return config;
4008 }
Romain Guy06882f82009-06-10 13:36:04 -07004009
Dianne Hackbornc485a602009-03-24 22:39:49 -07004010 boolean computeNewConfigurationLocked(Configuration config) {
4011 if (mDisplay == null) {
4012 return false;
4013 }
4014 mQueue.getInputConfiguration(config);
4015 final int dw = mDisplay.getWidth();
4016 final int dh = mDisplay.getHeight();
4017 int orientation = Configuration.ORIENTATION_SQUARE;
4018 if (dw < dh) {
4019 orientation = Configuration.ORIENTATION_PORTRAIT;
4020 } else if (dw > dh) {
4021 orientation = Configuration.ORIENTATION_LANDSCAPE;
4022 }
4023 config.orientation = orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004024
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004025 DisplayMetrics dm = new DisplayMetrics();
4026 mDisplay.getMetrics(dm);
4027 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4028
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004029 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07004030 // Note we only do this once because at this point we don't
4031 // expect the screen to change in this way at runtime, and want
4032 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07004033 int longSize = dw;
4034 int shortSize = dh;
4035 if (longSize < shortSize) {
4036 int tmp = longSize;
4037 longSize = shortSize;
4038 shortSize = tmp;
4039 }
4040 longSize = (int)(longSize/dm.density);
4041 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004042
Dianne Hackborn723738c2009-06-25 19:48:04 -07004043 // These semi-magic numbers define our compatibility modes for
4044 // applications with different screens. Don't change unless you
4045 // make sure to test lots and lots of apps!
4046 if (longSize < 470) {
4047 // This is shorter than an HVGA normal density screen (which
4048 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004049 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4050 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004051 } else {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004052 // Is this a large screen?
4053 if (longSize > 640 && shortSize >= 480) {
4054 // VGA or larger screens at medium density are the point
4055 // at which we consider it to be a large screen.
4056 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4057 } else {
4058 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
4059
4060 // If this screen is wider than normal HVGA, or taller
4061 // than FWVGA, then for old apps we want to run in size
4062 // compatibility mode.
4063 if (shortSize > 321 || longSize > 570) {
4064 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4065 }
4066 }
4067
4068 // Is this a long screen?
4069 if (((longSize*3)/5) >= (shortSize-1)) {
4070 // Anything wider than WVGA (5:3) is considering to be long.
4071 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4072 } else {
4073 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4074 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07004075 }
4076 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004077 config.screenLayout = mScreenLayout;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004078
Dianne Hackbornc485a602009-03-24 22:39:49 -07004079 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4080 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4081 mPolicy.adjustConfigurationLw(config);
4082 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 }
Romain Guy06882f82009-06-10 13:36:04 -07004084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 // -------------------------------------------------------------
4086 // Input Events and Focus Management
4087 // -------------------------------------------------------------
4088
4089 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07004090 long curTime = SystemClock.uptimeMillis();
4091
Michael Chane10de972009-05-18 11:24:50 -07004092 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07004093 if (mLastTouchEventType == eventType &&
4094 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4095 return;
4096 }
4097 mLastUserActivityCallTime = curTime;
4098 mLastTouchEventType = eventType;
4099 }
4100
4101 if (targetWin == null
4102 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
4103 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 }
4105 }
4106
4107 // tells if it's a cheek event or not -- this function is stateful
4108 private static final int EVENT_NONE = 0;
4109 private static final int EVENT_UNKNOWN = 0;
4110 private static final int EVENT_CHEEK = 0;
4111 private static final int EVENT_IGNORE_DURATION = 300; // ms
4112 private static final float CHEEK_THRESHOLD = 0.6f;
4113 private int mEventState = EVENT_NONE;
4114 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 private int eventType(MotionEvent ev) {
4117 float size = ev.getSize();
4118 switch (ev.getAction()) {
4119 case MotionEvent.ACTION_DOWN:
4120 mEventSize = size;
4121 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
4122 case MotionEvent.ACTION_UP:
4123 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004124 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 case MotionEvent.ACTION_MOVE:
4126 final int N = ev.getHistorySize();
4127 if (size > mEventSize) mEventSize = size;
4128 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
4129 for (int i=0; i<N; i++) {
4130 size = ev.getHistoricalSize(i);
4131 if (size > mEventSize) mEventSize = size;
4132 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
4133 }
4134 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
4135 return TOUCH_EVENT;
4136 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004137 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 }
4139 default:
4140 // not good
4141 return OTHER_EVENT;
4142 }
4143 }
4144
4145 /**
4146 * @return Returns true if event was dispatched, false if it was dropped for any reason
4147 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004148 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Log.v(TAG,
4150 "dispatchPointer " + ev);
4151
Michael Chan53071d62009-05-13 17:29:48 -07004152 if (MEASURE_LATENCY) {
4153 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
4154 }
4155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004157 ev, true, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158
Michael Chan53071d62009-05-13 17:29:48 -07004159 if (MEASURE_LATENCY) {
4160 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
4161 }
4162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07004164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 if (action == MotionEvent.ACTION_UP) {
4166 // let go of our target
4167 mKeyWaiter.mMotionTarget = null;
4168 mPowerManager.logPointerUpEvent();
4169 } else if (action == MotionEvent.ACTION_DOWN) {
4170 mPowerManager.logPointerDownEvent();
4171 }
4172
4173 if (targetObj == null) {
4174 // In this case we are either dropping the event, or have received
4175 // a move or up without a down. It is common to receive move
4176 // events in such a way, since this means the user is moving the
4177 // pointer without actually pressing down. All other cases should
4178 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07004179 if (action != MotionEvent.ACTION_MOVE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 Log.w(TAG, "No window to dispatch pointer action " + ev.getAction());
4181 }
4182 if (qev != null) {
4183 mQueue.recycleEvent(qev);
4184 }
4185 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004186 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 }
4188 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
4189 if (qev != null) {
4190 mQueue.recycleEvent(qev);
4191 }
4192 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004193 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 }
Romain Guy06882f82009-06-10 13:36:04 -07004195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07004197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07004199 final long eventTimeNano = ev.getEventTimeNano();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200
4201 //Log.i(TAG, "Sending " + ev + " to " + target);
4202
4203 if (uid != 0 && uid != target.mSession.mUid) {
4204 if (mContext.checkPermission(
4205 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4206 != PackageManager.PERMISSION_GRANTED) {
4207 Log.w(TAG, "Permission denied: injecting pointer event from pid "
4208 + pid + " uid " + uid + " to window " + target
4209 + " owned by uid " + target.mSession.mUid);
4210 if (qev != null) {
4211 mQueue.recycleEvent(qev);
4212 }
4213 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004214 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004215 }
4216 }
4217
Michael Chan53071d62009-05-13 17:29:48 -07004218 if (MEASURE_LATENCY) {
4219 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
4220 }
4221
Romain Guy06882f82009-06-10 13:36:04 -07004222 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
4224 //target wants to ignore fat touch events
4225 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
4226 //explicit flag to return without processing event further
4227 boolean returnFlag = false;
4228 if((action == MotionEvent.ACTION_DOWN)) {
4229 mFatTouch = false;
4230 if(cheekPress) {
4231 mFatTouch = true;
4232 returnFlag = true;
4233 }
4234 } else {
4235 if(action == MotionEvent.ACTION_UP) {
4236 if(mFatTouch) {
4237 //earlier even was invalid doesnt matter if current up is cheekpress or not
4238 mFatTouch = false;
4239 returnFlag = true;
4240 } else if(cheekPress) {
4241 //cancel the earlier event
4242 ev.setAction(MotionEvent.ACTION_CANCEL);
4243 action = MotionEvent.ACTION_CANCEL;
4244 }
4245 } else if(action == MotionEvent.ACTION_MOVE) {
4246 if(mFatTouch) {
4247 //two cases here
4248 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07004249 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 returnFlag = true;
4251 } else if(cheekPress) {
4252 //valid down followed by invalid moves
4253 //an invalid move have to cancel earlier action
4254 ev.setAction(MotionEvent.ACTION_CANCEL);
4255 action = MotionEvent.ACTION_CANCEL;
4256 if (DEBUG_INPUT) Log.v(TAG, "Sending cancel for invalid ACTION_MOVE");
4257 //note that the subsequent invalid moves will not get here
4258 mFatTouch = true;
4259 }
4260 }
4261 } //else if action
4262 if(returnFlag) {
4263 //recycle que, ev
4264 if (qev != null) {
4265 mQueue.recycleEvent(qev);
4266 }
4267 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004268 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 }
4270 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07004271
Michael Chan9f028e62009-08-04 17:37:46 -07004272 // Enable this for testing the "right" value
4273 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07004274 int max_events_per_sec = 35;
4275 try {
4276 max_events_per_sec = Integer.parseInt(SystemProperties
4277 .get("windowsmgr.max_events_per_sec"));
4278 if (max_events_per_sec < 1) {
4279 max_events_per_sec = 35;
4280 }
4281 } catch (NumberFormatException e) {
4282 }
4283 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
4284 }
4285
4286 /*
4287 * Throttle events to minimize CPU usage when there's a flood of events
4288 * e.g. constant contact with the screen
4289 */
4290 if (action == MotionEvent.ACTION_MOVE) {
4291 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
4292 long now = SystemClock.uptimeMillis();
4293 if (now < nextEventTime) {
4294 try {
4295 Thread.sleep(nextEventTime - now);
4296 } catch (InterruptedException e) {
4297 }
4298 mLastTouchEventTime = nextEventTime;
4299 } else {
4300 mLastTouchEventTime = now;
4301 }
4302 }
4303
Michael Chan53071d62009-05-13 17:29:48 -07004304 if (MEASURE_LATENCY) {
4305 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
4306 }
4307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 synchronized(mWindowMap) {
4309 if (qev != null && action == MotionEvent.ACTION_MOVE) {
4310 mKeyWaiter.bindTargetWindowLocked(target,
4311 KeyWaiter.RETURN_PENDING_POINTER, qev);
4312 ev = null;
4313 } else {
4314 if (action == MotionEvent.ACTION_DOWN) {
4315 WindowState out = mKeyWaiter.mOutsideTouchTargets;
4316 if (out != null) {
4317 MotionEvent oev = MotionEvent.obtain(ev);
4318 oev.setAction(MotionEvent.ACTION_OUTSIDE);
4319 do {
4320 final Rect frame = out.mFrame;
4321 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
4322 try {
4323 out.mClient.dispatchPointer(oev, eventTime);
4324 } catch (android.os.RemoteException e) {
4325 Log.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
4326 }
4327 oev.offsetLocation((float)frame.left, (float)frame.top);
4328 out = out.mNextOutsideTouch;
4329 } while (out != null);
4330 mKeyWaiter.mOutsideTouchTargets = null;
4331 }
4332 }
4333 final Rect frame = target.mFrame;
4334 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
4335 mKeyWaiter.bindTargetWindowLocked(target);
4336 }
4337 }
Romain Guy06882f82009-06-10 13:36:04 -07004338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 // finally offset the event to the target's coordinate system and
4340 // dispatch the event.
4341 try {
4342 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
4343 Log.v(TAG, "Delivering pointer " + qev + " to " + target);
4344 }
Michael Chan53071d62009-05-13 17:29:48 -07004345
4346 if (MEASURE_LATENCY) {
4347 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
4348 }
4349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 target.mClient.dispatchPointer(ev, eventTime);
Michael Chan53071d62009-05-13 17:29:48 -07004351
4352 if (MEASURE_LATENCY) {
4353 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
4354 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07004355 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 } catch (android.os.RemoteException e) {
4357 Log.i(TAG, "WINDOW DIED during motion dispatch: " + target);
4358 mKeyWaiter.mMotionTarget = null;
4359 try {
4360 removeWindow(target.mSession, target.mClient);
4361 } catch (java.util.NoSuchElementException ex) {
4362 // This will happen if the window has already been
4363 // removed.
4364 }
4365 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07004366 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 }
Romain Guy06882f82009-06-10 13:36:04 -07004368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 /**
4370 * @return Returns true if event was dispatched, false if it was dropped for any reason
4371 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004372 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 if (DEBUG_INPUT) Log.v(
4374 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07004375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004377 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 if (focusObj == null) {
4379 Log.w(TAG, "No focus window, dropping trackball: " + ev);
4380 if (qev != null) {
4381 mQueue.recycleEvent(qev);
4382 }
4383 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004384 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 }
4386 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
4387 if (qev != null) {
4388 mQueue.recycleEvent(qev);
4389 }
4390 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004391 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 }
Romain Guy06882f82009-06-10 13:36:04 -07004393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07004395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 if (uid != 0 && uid != focus.mSession.mUid) {
4397 if (mContext.checkPermission(
4398 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4399 != PackageManager.PERMISSION_GRANTED) {
4400 Log.w(TAG, "Permission denied: injecting key event from pid "
4401 + pid + " uid " + uid + " to window " + focus
4402 + " owned by uid " + focus.mSession.mUid);
4403 if (qev != null) {
4404 mQueue.recycleEvent(qev);
4405 }
4406 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004407 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 }
4409 }
Romain Guy06882f82009-06-10 13:36:04 -07004410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07004412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 synchronized(mWindowMap) {
4414 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
4415 mKeyWaiter.bindTargetWindowLocked(focus,
4416 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
4417 // We don't deliver movement events to the client, we hold
4418 // them and wait for them to call back.
4419 ev = null;
4420 } else {
4421 mKeyWaiter.bindTargetWindowLocked(focus);
4422 }
4423 }
Romain Guy06882f82009-06-10 13:36:04 -07004424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 try {
4426 focus.mClient.dispatchTrackball(ev, eventTime);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004427 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 } catch (android.os.RemoteException e) {
4429 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
4430 try {
4431 removeWindow(focus.mSession, focus.mClient);
4432 } catch (java.util.NoSuchElementException ex) {
4433 // This will happen if the window has already been
4434 // removed.
4435 }
4436 }
Romain Guy06882f82009-06-10 13:36:04 -07004437
Dianne Hackborncfaef692009-06-15 14:24:44 -07004438 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 }
Romain Guy06882f82009-06-10 13:36:04 -07004440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 /**
4442 * @return Returns true if event was dispatched, false if it was dropped for any reason
4443 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004444 private int dispatchKey(KeyEvent event, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 if (DEBUG_INPUT) Log.v(TAG, "Dispatch key: " + event);
4446
4447 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004448 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004449 if (focusObj == null) {
4450 Log.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004451 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 }
4453 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004454 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 }
Romain Guy06882f82009-06-10 13:36:04 -07004456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07004458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 if (DEBUG_INPUT) Log.v(
4460 TAG, "Dispatching to " + focus + ": " + event);
4461
4462 if (uid != 0 && uid != focus.mSession.mUid) {
4463 if (mContext.checkPermission(
4464 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4465 != PackageManager.PERMISSION_GRANTED) {
4466 Log.w(TAG, "Permission denied: injecting key event from pid "
4467 + pid + " uid " + uid + " to window " + focus
4468 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004469 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 }
4471 }
Romain Guy06882f82009-06-10 13:36:04 -07004472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 synchronized(mWindowMap) {
4474 mKeyWaiter.bindTargetWindowLocked(focus);
4475 }
4476
4477 // NOSHIP extra state logging
4478 mKeyWaiter.recordDispatchState(event, focus);
4479 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07004480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 try {
4482 if (DEBUG_INPUT || DEBUG_FOCUS) {
4483 Log.v(TAG, "Delivering key " + event.getKeyCode()
4484 + " to " + focus);
4485 }
4486 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004487 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 } catch (android.os.RemoteException e) {
4489 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
4490 try {
4491 removeWindow(focus.mSession, focus.mClient);
4492 } catch (java.util.NoSuchElementException ex) {
4493 // This will happen if the window has already been
4494 // removed.
4495 }
4496 }
Romain Guy06882f82009-06-10 13:36:04 -07004497
Dianne Hackborncfaef692009-06-15 14:24:44 -07004498 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499 }
Romain Guy06882f82009-06-10 13:36:04 -07004500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 public void pauseKeyDispatching(IBinder _token) {
4502 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4503 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004504 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506
4507 synchronized (mWindowMap) {
4508 WindowToken token = mTokenMap.get(_token);
4509 if (token != null) {
4510 mKeyWaiter.pauseDispatchingLocked(token);
4511 }
4512 }
4513 }
4514
4515 public void resumeKeyDispatching(IBinder _token) {
4516 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4517 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004518 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 }
4520
4521 synchronized (mWindowMap) {
4522 WindowToken token = mTokenMap.get(_token);
4523 if (token != null) {
4524 mKeyWaiter.resumeDispatchingLocked(token);
4525 }
4526 }
4527 }
4528
4529 public void setEventDispatching(boolean enabled) {
4530 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4531 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004532 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 }
4534
4535 synchronized (mWindowMap) {
4536 mKeyWaiter.setEventDispatchingLocked(enabled);
4537 }
4538 }
Romain Guy06882f82009-06-10 13:36:04 -07004539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 /**
4541 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07004542 *
4543 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 * {@link SystemClock#uptimeMillis()} as the timebase.)
4545 * @param sync If true, wait for the event to be completed before returning to the caller.
4546 * @return Returns true if event was dispatched, false if it was dropped for any reason
4547 */
4548 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
4549 long downTime = ev.getDownTime();
4550 long eventTime = ev.getEventTime();
4551
4552 int action = ev.getAction();
4553 int code = ev.getKeyCode();
4554 int repeatCount = ev.getRepeatCount();
4555 int metaState = ev.getMetaState();
4556 int deviceId = ev.getDeviceId();
4557 int scancode = ev.getScanCode();
4558
4559 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
4560 if (downTime == 0) downTime = eventTime;
4561
4562 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07004563 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004564
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004565 final int pid = Binder.getCallingPid();
4566 final int uid = Binder.getCallingUid();
4567 final long ident = Binder.clearCallingIdentity();
4568 final int result = dispatchKey(newEvent, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004570 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004572 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004573 switch (result) {
4574 case INJECT_NO_PERMISSION:
4575 throw new SecurityException(
4576 "Injecting to another application requires INJECT_EVENT permission");
4577 case INJECT_SUCCEEDED:
4578 return true;
4579 }
4580 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 }
4582
4583 /**
4584 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07004585 *
4586 * @param ev A motion event describing the pointer (touch) action. (As noted in
4587 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 * {@link SystemClock#uptimeMillis()} as the timebase.)
4589 * @param sync If true, wait for the event to be completed before returning to the caller.
4590 * @return Returns true if event was dispatched, false if it was dropped for any reason
4591 */
4592 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004593 final int pid = Binder.getCallingPid();
4594 final int uid = Binder.getCallingUid();
4595 final long ident = Binder.clearCallingIdentity();
4596 final int result = dispatchPointer(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004598 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004600 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004601 switch (result) {
4602 case INJECT_NO_PERMISSION:
4603 throw new SecurityException(
4604 "Injecting to another application requires INJECT_EVENT permission");
4605 case INJECT_SUCCEEDED:
4606 return true;
4607 }
4608 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 }
Romain Guy06882f82009-06-10 13:36:04 -07004610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 /**
4612 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07004613 *
4614 * @param ev A motion event describing the trackball action. (As noted in
4615 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 * {@link SystemClock#uptimeMillis()} as the timebase.)
4617 * @param sync If true, wait for the event to be completed before returning to the caller.
4618 * @return Returns true if event was dispatched, false if it was dropped for any reason
4619 */
4620 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004621 final int pid = Binder.getCallingPid();
4622 final int uid = Binder.getCallingUid();
4623 final long ident = Binder.clearCallingIdentity();
4624 final int result = dispatchTrackball(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004626 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004628 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004629 switch (result) {
4630 case INJECT_NO_PERMISSION:
4631 throw new SecurityException(
4632 "Injecting to another application requires INJECT_EVENT permission");
4633 case INJECT_SUCCEEDED:
4634 return true;
4635 }
4636 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 }
Romain Guy06882f82009-06-10 13:36:04 -07004638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 private WindowState getFocusedWindow() {
4640 synchronized (mWindowMap) {
4641 return getFocusedWindowLocked();
4642 }
4643 }
4644
4645 private WindowState getFocusedWindowLocked() {
4646 return mCurrentFocus;
4647 }
Romain Guy06882f82009-06-10 13:36:04 -07004648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 /**
4650 * This class holds the state for dispatching key events. This state
4651 * is protected by the KeyWaiter instance, NOT by the window lock. You
4652 * can be holding the main window lock while acquire the KeyWaiter lock,
4653 * but not the other way around.
4654 */
4655 final class KeyWaiter {
4656 // NOSHIP debugging
4657 public class DispatchState {
4658 private KeyEvent event;
4659 private WindowState focus;
4660 private long time;
4661 private WindowState lastWin;
4662 private IBinder lastBinder;
4663 private boolean finished;
4664 private boolean gotFirstWindow;
4665 private boolean eventDispatching;
4666 private long timeToSwitch;
4667 private boolean wasFrozen;
4668 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08004669 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07004670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 DispatchState(KeyEvent theEvent, WindowState theFocus) {
4672 focus = theFocus;
4673 event = theEvent;
4674 time = System.currentTimeMillis();
4675 // snapshot KeyWaiter state
4676 lastWin = mLastWin;
4677 lastBinder = mLastBinder;
4678 finished = mFinished;
4679 gotFirstWindow = mGotFirstWindow;
4680 eventDispatching = mEventDispatching;
4681 timeToSwitch = mTimeToSwitch;
4682 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08004683 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 // cache the paused state at ctor time as well
4685 if (theFocus == null || theFocus.mToken == null) {
4686 Log.i(TAG, "focus " + theFocus + " mToken is null at event dispatch!");
4687 focusPaused = false;
4688 } else {
4689 focusPaused = theFocus.mToken.paused;
4690 }
4691 }
Romain Guy06882f82009-06-10 13:36:04 -07004692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 public String toString() {
4694 return "{{" + event + " to " + focus + " @ " + time
4695 + " lw=" + lastWin + " lb=" + lastBinder
4696 + " fin=" + finished + " gfw=" + gotFirstWindow
4697 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08004698 + " wf=" + wasFrozen + " fp=" + focusPaused
4699 + " mcf=" + mCurrentFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 }
4701 };
4702 private DispatchState mDispatchState = null;
4703 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
4704 mDispatchState = new DispatchState(theEvent, theFocus);
4705 }
4706 // END NOSHIP
4707
4708 public static final int RETURN_NOTHING = 0;
4709 public static final int RETURN_PENDING_POINTER = 1;
4710 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07004711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 final Object SKIP_TARGET_TOKEN = new Object();
4713 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07004714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 private WindowState mLastWin = null;
4716 private IBinder mLastBinder = null;
4717 private boolean mFinished = true;
4718 private boolean mGotFirstWindow = false;
4719 private boolean mEventDispatching = true;
4720 private long mTimeToSwitch = 0;
4721 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07004722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 // Target of Motion events
4724 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07004725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 // Windows above the target who would like to receive an "outside"
4727 // touch event for any down events outside of them.
4728 WindowState mOutsideTouchTargets;
4729
4730 /**
4731 * Wait for the last event dispatch to complete, then find the next
4732 * target that should receive the given event and wait for that one
4733 * to be ready to receive it.
4734 */
4735 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
4736 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004737 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004738 long startTime = SystemClock.uptimeMillis();
4739 long keyDispatchingTimeout = 5 * 1000;
4740 long waitedFor = 0;
4741
4742 while (true) {
4743 // Figure out which window we care about. It is either the
4744 // last window we are waiting to have process the event or,
4745 // if none, then the next window we think the event should go
4746 // to. Note: we retrieve mLastWin outside of the lock, so
4747 // it may change before we lock. Thus we must check it again.
4748 WindowState targetWin = mLastWin;
4749 boolean targetIsNew = targetWin == null;
4750 if (DEBUG_INPUT) Log.v(
4751 TAG, "waitForLastKey: mFinished=" + mFinished +
4752 ", mLastWin=" + mLastWin);
4753 if (targetIsNew) {
4754 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004755 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 if (target == SKIP_TARGET_TOKEN) {
4757 // The user has pressed a special key, and we are
4758 // dropping all pending events before it.
4759 if (DEBUG_INPUT) Log.v(TAG, "Skipping: " + nextKey
4760 + " " + nextMotion);
4761 return null;
4762 }
4763 if (target == CONSUMED_EVENT_TOKEN) {
4764 if (DEBUG_INPUT) Log.v(TAG, "Consumed: " + nextKey
4765 + " " + nextMotion);
4766 return target;
4767 }
4768 targetWin = (WindowState)target;
4769 }
Romain Guy06882f82009-06-10 13:36:04 -07004770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07004772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 // Now: is it okay to send the next event to this window?
4774 synchronized (this) {
4775 // First: did we come here based on the last window not
4776 // being null, but it changed by the time we got here?
4777 // If so, try again.
4778 if (!targetIsNew && mLastWin == null) {
4779 continue;
4780 }
Romain Guy06882f82009-06-10 13:36:04 -07004781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 // We never dispatch events if not finished with the
4783 // last one, or the display is frozen.
4784 if (mFinished && !mDisplayFrozen) {
4785 // If event dispatching is disabled, then we
4786 // just consume the events.
4787 if (!mEventDispatching) {
4788 if (DEBUG_INPUT) Log.v(TAG,
4789 "Skipping event; dispatching disabled: "
4790 + nextKey + " " + nextMotion);
4791 return null;
4792 }
4793 if (targetWin != null) {
4794 // If this is a new target, and that target is not
4795 // paused or unresponsive, then all looks good to
4796 // handle the event.
4797 if (targetIsNew && !targetWin.mToken.paused) {
4798 return targetWin;
4799 }
Romain Guy06882f82009-06-10 13:36:04 -07004800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004801 // If we didn't find a target window, and there is no
4802 // focused app window, then just eat the events.
4803 } else if (mFocusedApp == null) {
4804 if (DEBUG_INPUT) Log.v(TAG,
4805 "Skipping event; no focused app: "
4806 + nextKey + " " + nextMotion);
4807 return null;
4808 }
4809 }
Romain Guy06882f82009-06-10 13:36:04 -07004810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 if (DEBUG_INPUT) Log.v(
4812 TAG, "Waiting for last key in " + mLastBinder
4813 + " target=" + targetWin
4814 + " mFinished=" + mFinished
4815 + " mDisplayFrozen=" + mDisplayFrozen
4816 + " targetIsNew=" + targetIsNew
4817 + " paused="
4818 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08004819 + " mFocusedApp=" + mFocusedApp
4820 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07004821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 targetApp = targetWin != null
4823 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07004824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004825 long curTimeout = keyDispatchingTimeout;
4826 if (mTimeToSwitch != 0) {
4827 long now = SystemClock.uptimeMillis();
4828 if (mTimeToSwitch <= now) {
4829 // If an app switch key has been pressed, and we have
4830 // waited too long for the current app to finish
4831 // processing keys, then wait no more!
4832 doFinishedKeyLocked(true);
4833 continue;
4834 }
4835 long switchTimeout = mTimeToSwitch - now;
4836 if (curTimeout > switchTimeout) {
4837 curTimeout = switchTimeout;
4838 }
4839 }
Romain Guy06882f82009-06-10 13:36:04 -07004840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 try {
4842 // after that continue
4843 // processing keys, so we don't get stuck.
4844 if (DEBUG_INPUT) Log.v(
4845 TAG, "Waiting for key dispatch: " + curTimeout);
4846 wait(curTimeout);
4847 if (DEBUG_INPUT) Log.v(TAG, "Finished waiting @"
4848 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08004849 + startTime + " switchTime=" + mTimeToSwitch
4850 + " target=" + targetWin + " mLW=" + mLastWin
4851 + " mLB=" + mLastBinder + " fin=" + mFinished
4852 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 } catch (InterruptedException e) {
4854 }
4855 }
4856
4857 // If we were frozen during configuration change, restart the
4858 // timeout checks from now; otherwise look at whether we timed
4859 // out before awakening.
4860 if (mWasFrozen) {
4861 waitedFor = 0;
4862 mWasFrozen = false;
4863 } else {
4864 waitedFor = SystemClock.uptimeMillis() - startTime;
4865 }
4866
4867 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
4868 IApplicationToken at = null;
4869 synchronized (this) {
4870 Log.w(TAG, "Key dispatching timed out sending to " +
4871 (targetWin != null ? targetWin.mAttrs.getTitle()
4872 : "<null>"));
4873 // NOSHIP debugging
4874 Log.w(TAG, "Dispatch state: " + mDispatchState);
4875 Log.w(TAG, "Current state: " + new DispatchState(nextKey, targetWin));
4876 // END NOSHIP
4877 //dump();
4878 if (targetWin != null) {
4879 at = targetWin.getAppToken();
4880 } else if (targetApp != null) {
4881 at = targetApp.appToken;
4882 }
4883 }
4884
4885 boolean abort = true;
4886 if (at != null) {
4887 try {
4888 long timeout = at.getKeyDispatchingTimeout();
4889 if (timeout > waitedFor) {
4890 // we did not wait the proper amount of time for this application.
4891 // set the timeout to be the real timeout and wait again.
4892 keyDispatchingTimeout = timeout - waitedFor;
4893 continue;
4894 } else {
4895 abort = at.keyDispatchingTimedOut();
4896 }
4897 } catch (RemoteException ex) {
4898 }
4899 }
4900
4901 synchronized (this) {
4902 if (abort && (mLastWin == targetWin || targetWin == null)) {
4903 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07004904 if (mLastWin != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 if (DEBUG_INPUT) Log.v(TAG,
4906 "Window " + mLastWin +
4907 " timed out on key input");
4908 if (mLastWin.mToken.paused) {
4909 Log.w(TAG, "Un-pausing dispatching to this window");
4910 mLastWin.mToken.paused = false;
4911 }
4912 }
4913 if (mMotionTarget == targetWin) {
4914 mMotionTarget = null;
4915 }
4916 mLastWin = null;
4917 mLastBinder = null;
4918 if (failIfTimeout || targetWin == null) {
4919 return null;
4920 }
4921 } else {
4922 Log.w(TAG, "Continuing to wait for key to be dispatched");
4923 startTime = SystemClock.uptimeMillis();
4924 }
4925 }
4926 }
4927 }
4928 }
Romain Guy06882f82009-06-10 13:36:04 -07004929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004931 MotionEvent nextMotion, boolean isPointerEvent,
4932 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07004934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 if (nextKey != null) {
4936 // Find the target window for a normal key event.
4937 final int keycode = nextKey.getKeyCode();
4938 final int repeatCount = nextKey.getRepeatCount();
4939 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
4940 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004943 if (callingUid == 0 ||
4944 mContext.checkPermission(
4945 android.Manifest.permission.INJECT_EVENTS,
4946 callingPid, callingUid)
4947 == PackageManager.PERMISSION_GRANTED) {
4948 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07004949 nextKey.getMetaState(), down, repeatCount,
4950 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 Log.w(TAG, "Event timeout during app switch: dropping "
4953 + nextKey);
4954 return SKIP_TARGET_TOKEN;
4955 }
Romain Guy06882f82009-06-10 13:36:04 -07004956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07004958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 WindowState focus = null;
4960 synchronized(mWindowMap) {
4961 focus = getFocusedWindowLocked();
4962 }
Romain Guy06882f82009-06-10 13:36:04 -07004963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07004965
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004966 if (callingUid == 0 ||
4967 (focus != null && callingUid == focus.mSession.mUid) ||
4968 mContext.checkPermission(
4969 android.Manifest.permission.INJECT_EVENTS,
4970 callingPid, callingUid)
4971 == PackageManager.PERMISSION_GRANTED) {
4972 if (mPolicy.interceptKeyTi(focus,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07004973 keycode, nextKey.getMetaState(), down, repeatCount,
4974 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004975 return CONSUMED_EVENT_TOKEN;
4976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 }
Romain Guy06882f82009-06-10 13:36:04 -07004978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07004980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 } else if (!isPointerEvent) {
4982 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
4983 if (!dispatch) {
4984 Log.w(TAG, "Event timeout during app switch: dropping trackball "
4985 + nextMotion);
4986 return SKIP_TARGET_TOKEN;
4987 }
Romain Guy06882f82009-06-10 13:36:04 -07004988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 WindowState focus = null;
4990 synchronized(mWindowMap) {
4991 focus = getFocusedWindowLocked();
4992 }
Romain Guy06882f82009-06-10 13:36:04 -07004993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
4995 return focus;
4996 }
Romain Guy06882f82009-06-10 13:36:04 -07004997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 if (nextMotion == null) {
4999 return SKIP_TARGET_TOKEN;
5000 }
Romain Guy06882f82009-06-10 13:36:04 -07005001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5003 KeyEvent.KEYCODE_UNKNOWN);
5004 if (!dispatch) {
5005 Log.w(TAG, "Event timeout during app switch: dropping pointer "
5006 + nextMotion);
5007 return SKIP_TARGET_TOKEN;
5008 }
Romain Guy06882f82009-06-10 13:36:04 -07005009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005010 // Find the target window for a pointer event.
5011 int action = nextMotion.getAction();
5012 final float xf = nextMotion.getX();
5013 final float yf = nextMotion.getY();
5014 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 final boolean screenWasOff = qev != null
5017 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07005018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07005020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 synchronized(mWindowMap) {
5022 synchronized (this) {
5023 if (action == MotionEvent.ACTION_DOWN) {
5024 if (mMotionTarget != null) {
5025 // this is weird, we got a pen down, but we thought it was
5026 // already down!
5027 // XXX: We should probably send an ACTION_UP to the current
5028 // target.
5029 Log.w(TAG, "Pointer down received while already down in: "
5030 + mMotionTarget);
5031 mMotionTarget = null;
5032 }
Romain Guy06882f82009-06-10 13:36:04 -07005033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 // ACTION_DOWN is special, because we need to lock next events to
5035 // the window we'll land onto.
5036 final int x = (int)xf;
5037 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07005038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 final ArrayList windows = mWindows;
5040 final int N = windows.size();
5041 WindowState topErrWindow = null;
5042 final Rect tmpRect = mTempRect;
5043 for (int i=N-1; i>=0; i--) {
5044 WindowState child = (WindowState)windows.get(i);
5045 //Log.i(TAG, "Checking dispatch to: " + child);
5046 final int flags = child.mAttrs.flags;
5047 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5048 if (topErrWindow == null) {
5049 topErrWindow = child;
5050 }
5051 }
5052 if (!child.isVisibleLw()) {
5053 //Log.i(TAG, "Not visible!");
5054 continue;
5055 }
5056 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
5057 //Log.i(TAG, "Not touchable!");
5058 if ((flags & WindowManager.LayoutParams
5059 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5060 child.mNextOutsideTouch = mOutsideTouchTargets;
5061 mOutsideTouchTargets = child;
5062 }
5063 continue;
5064 }
5065 tmpRect.set(child.mFrame);
5066 if (child.mTouchableInsets == ViewTreeObserver
5067 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5068 // The touch is inside of the window if it is
5069 // inside the frame, AND the content part of that
5070 // frame that was given by the application.
5071 tmpRect.left += child.mGivenContentInsets.left;
5072 tmpRect.top += child.mGivenContentInsets.top;
5073 tmpRect.right -= child.mGivenContentInsets.right;
5074 tmpRect.bottom -= child.mGivenContentInsets.bottom;
5075 } else if (child.mTouchableInsets == ViewTreeObserver
5076 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
5077 // The touch is inside of the window if it is
5078 // inside the frame, AND the visible part of that
5079 // frame that was given by the application.
5080 tmpRect.left += child.mGivenVisibleInsets.left;
5081 tmpRect.top += child.mGivenVisibleInsets.top;
5082 tmpRect.right -= child.mGivenVisibleInsets.right;
5083 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
5084 }
5085 final int touchFlags = flags &
5086 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5087 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
5088 if (tmpRect.contains(x, y) || touchFlags == 0) {
5089 //Log.i(TAG, "Using this target!");
5090 if (!screenWasOff || (flags &
5091 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
5092 mMotionTarget = child;
5093 } else {
5094 //Log.i(TAG, "Waking, skip!");
5095 mMotionTarget = null;
5096 }
5097 break;
5098 }
Romain Guy06882f82009-06-10 13:36:04 -07005099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 if ((flags & WindowManager.LayoutParams
5101 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5102 child.mNextOutsideTouch = mOutsideTouchTargets;
5103 mOutsideTouchTargets = child;
5104 //Log.i(TAG, "Adding to outside target list: " + child);
5105 }
5106 }
5107
5108 // if there's an error window but it's not accepting
5109 // focus (typically because it is not yet visible) just
5110 // wait for it -- any other focused window may in fact
5111 // be in ANR state.
5112 if (topErrWindow != null && mMotionTarget != topErrWindow) {
5113 mMotionTarget = null;
5114 }
5115 }
Romain Guy06882f82009-06-10 13:36:04 -07005116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005117 target = mMotionTarget;
5118 }
5119 }
Romain Guy06882f82009-06-10 13:36:04 -07005120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07005122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 // Pointer events are a little different -- if there isn't a
5124 // target found for any event, then just drop it.
5125 return target != null ? target : SKIP_TARGET_TOKEN;
5126 }
Romain Guy06882f82009-06-10 13:36:04 -07005127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 boolean checkShouldDispatchKey(int keycode) {
5129 synchronized (this) {
5130 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
5131 mTimeToSwitch = 0;
5132 return true;
5133 }
5134 if (mTimeToSwitch != 0
5135 && mTimeToSwitch < SystemClock.uptimeMillis()) {
5136 return false;
5137 }
5138 return true;
5139 }
5140 }
Romain Guy06882f82009-06-10 13:36:04 -07005141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 void bindTargetWindowLocked(WindowState win,
5143 int pendingWhat, QueuedEvent pendingMotion) {
5144 synchronized (this) {
5145 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
5146 }
5147 }
Romain Guy06882f82009-06-10 13:36:04 -07005148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 void bindTargetWindowLocked(WindowState win) {
5150 synchronized (this) {
5151 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
5152 }
5153 }
5154
5155 void bindTargetWindowLockedLocked(WindowState win,
5156 int pendingWhat, QueuedEvent pendingMotion) {
5157 mLastWin = win;
5158 mLastBinder = win.mClient.asBinder();
5159 mFinished = false;
5160 if (pendingMotion != null) {
5161 final Session s = win.mSession;
5162 if (pendingWhat == RETURN_PENDING_POINTER) {
5163 releasePendingPointerLocked(s);
5164 s.mPendingPointerMove = pendingMotion;
5165 s.mPendingPointerWindow = win;
Romain Guy06882f82009-06-10 13:36:04 -07005166 if (DEBUG_INPUT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 "bindTargetToWindow " + s.mPendingPointerMove);
5168 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
5169 releasePendingTrackballLocked(s);
5170 s.mPendingTrackballMove = pendingMotion;
5171 s.mPendingTrackballWindow = win;
5172 }
5173 }
5174 }
Romain Guy06882f82009-06-10 13:36:04 -07005175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 void releasePendingPointerLocked(Session s) {
5177 if (DEBUG_INPUT) Log.v(TAG,
5178 "releasePendingPointer " + s.mPendingPointerMove);
5179 if (s.mPendingPointerMove != null) {
5180 mQueue.recycleEvent(s.mPendingPointerMove);
5181 s.mPendingPointerMove = null;
5182 }
5183 }
Romain Guy06882f82009-06-10 13:36:04 -07005184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 void releasePendingTrackballLocked(Session s) {
5186 if (s.mPendingTrackballMove != null) {
5187 mQueue.recycleEvent(s.mPendingTrackballMove);
5188 s.mPendingTrackballMove = null;
5189 }
5190 }
Romain Guy06882f82009-06-10 13:36:04 -07005191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 MotionEvent finishedKey(Session session, IWindow client, boolean force,
5193 int returnWhat) {
5194 if (DEBUG_INPUT) Log.v(
5195 TAG, "finishedKey: client=" + client + ", force=" + force);
5196
5197 if (client == null) {
5198 return null;
5199 }
5200
5201 synchronized (this) {
5202 if (DEBUG_INPUT) Log.v(
5203 TAG, "finishedKey: client=" + client.asBinder()
5204 + ", force=" + force + ", last=" + mLastBinder
5205 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
5206
5207 QueuedEvent qev = null;
5208 WindowState win = null;
5209 if (returnWhat == RETURN_PENDING_POINTER) {
5210 qev = session.mPendingPointerMove;
5211 win = session.mPendingPointerWindow;
5212 session.mPendingPointerMove = null;
5213 session.mPendingPointerWindow = null;
5214 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
5215 qev = session.mPendingTrackballMove;
5216 win = session.mPendingTrackballWindow;
5217 session.mPendingTrackballMove = null;
5218 session.mPendingTrackballWindow = null;
5219 }
Romain Guy06882f82009-06-10 13:36:04 -07005220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 if (mLastBinder == client.asBinder()) {
5222 if (DEBUG_INPUT) Log.v(
5223 TAG, "finishedKey: last paused="
5224 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
5225 if (mLastWin != null && (!mLastWin.mToken.paused || force
5226 || !mEventDispatching)) {
5227 doFinishedKeyLocked(false);
5228 } else {
5229 // Make sure to wake up anyone currently waiting to
5230 // dispatch a key, so they can re-evaluate their
5231 // current situation.
5232 mFinished = true;
5233 notifyAll();
5234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 }
Romain Guy06882f82009-06-10 13:36:04 -07005236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005237 if (qev != null) {
5238 MotionEvent res = (MotionEvent)qev.event;
5239 if (DEBUG_INPUT) Log.v(TAG,
5240 "Returning pending motion: " + res);
5241 mQueue.recycleEvent(qev);
5242 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
5243 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
5244 }
5245 return res;
5246 }
5247 return null;
5248 }
5249 }
5250
5251 void tickle() {
5252 synchronized (this) {
5253 notifyAll();
5254 }
5255 }
Romain Guy06882f82009-06-10 13:36:04 -07005256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 void handleNewWindowLocked(WindowState newWindow) {
5258 if (!newWindow.canReceiveKeys()) {
5259 return;
5260 }
5261 synchronized (this) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005262 if (DEBUG_INPUT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 TAG, "New key dispatch window: win="
5264 + newWindow.mClient.asBinder()
5265 + ", last=" + mLastBinder
5266 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
5267 + "), finished=" + mFinished + ", paused="
5268 + newWindow.mToken.paused);
5269
5270 // Displaying a window implicitly causes dispatching to
5271 // be unpaused. (This is to protect against bugs if someone
5272 // pauses dispatching but forgets to resume.)
5273 newWindow.mToken.paused = false;
5274
5275 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276
5277 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
5278 if (DEBUG_INPUT) Log.v(TAG,
5279 "New SYSTEM_ERROR window; resetting state");
5280 mLastWin = null;
5281 mLastBinder = null;
5282 mMotionTarget = null;
5283 mFinished = true;
5284 } else if (mLastWin != null) {
5285 // If the new window is above the window we are
5286 // waiting on, then stop waiting and let key dispatching
5287 // start on the new guy.
5288 if (DEBUG_INPUT) Log.v(
5289 TAG, "Last win layer=" + mLastWin.mLayer
5290 + ", new win layer=" + newWindow.mLayer);
5291 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005292 // The new window is above the old; finish pending input to the last
5293 // window and start directing it to the new one.
5294 mLastWin.mToken.paused = false;
5295 doFinishedKeyLocked(true); // does a notifyAll()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 }
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005297 // Either the new window is lower, so there is no need to wake key waiters,
5298 // or we just finished key input to the previous window, which implicitly
5299 // notified the key waiters. In both cases, we don't need to issue the
5300 // notification here.
5301 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 }
5303
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005304 // Now that we've put a new window state in place, make the event waiter
5305 // take notice and retarget its attentions.
5306 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 }
5308 }
5309
5310 void pauseDispatchingLocked(WindowToken token) {
5311 synchronized (this)
5312 {
5313 if (DEBUG_INPUT) Log.v(TAG, "Pausing WindowToken " + token);
5314 token.paused = true;
5315
5316 /*
5317 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
5318 mPaused = true;
5319 } else {
5320 if (mLastWin == null) {
Dave Bortcfe65242009-04-09 14:51:04 -07005321 Log.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 } else if (mFinished) {
Dave Bortcfe65242009-04-09 14:51:04 -07005323 Log.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 } else {
Dave Bortcfe65242009-04-09 14:51:04 -07005325 Log.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 }
5327 }
5328 */
5329 }
5330 }
5331
5332 void resumeDispatchingLocked(WindowToken token) {
5333 synchronized (this) {
5334 if (token.paused) {
5335 if (DEBUG_INPUT) Log.v(
5336 TAG, "Resuming WindowToken " + token
5337 + ", last=" + mLastBinder
5338 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
5339 + "), finished=" + mFinished + ", paused="
5340 + token.paused);
5341 token.paused = false;
5342 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
5343 doFinishedKeyLocked(true);
5344 } else {
5345 notifyAll();
5346 }
5347 }
5348 }
5349 }
5350
5351 void setEventDispatchingLocked(boolean enabled) {
5352 synchronized (this) {
5353 mEventDispatching = enabled;
5354 notifyAll();
5355 }
5356 }
Romain Guy06882f82009-06-10 13:36:04 -07005357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 void appSwitchComing() {
5359 synchronized (this) {
5360 // Don't wait for more than .5 seconds for app to finish
5361 // processing the pending events.
5362 long now = SystemClock.uptimeMillis() + 500;
5363 if (DEBUG_INPUT) Log.v(TAG, "appSwitchComing: " + now);
5364 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
5365 mTimeToSwitch = now;
5366 }
5367 notifyAll();
5368 }
5369 }
Romain Guy06882f82009-06-10 13:36:04 -07005370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005371 private final void doFinishedKeyLocked(boolean doRecycle) {
5372 if (mLastWin != null) {
5373 releasePendingPointerLocked(mLastWin.mSession);
5374 releasePendingTrackballLocked(mLastWin.mSession);
5375 }
Romain Guy06882f82009-06-10 13:36:04 -07005376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 if (mLastWin == null || !mLastWin.mToken.paused
5378 || !mLastWin.isVisibleLw()) {
5379 // If the current window has been paused, we aren't -really-
5380 // finished... so let the waiters still wait.
5381 mLastWin = null;
5382 mLastBinder = null;
5383 }
5384 mFinished = true;
5385 notifyAll();
5386 }
5387 }
5388
5389 private class KeyQ extends KeyInputQueue
5390 implements KeyInputQueue.FilterCallback {
5391 PowerManager.WakeLock mHoldingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07005392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005394 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
5396 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
5397 "KEEP_SCREEN_ON_FLAG");
5398 mHoldingScreen.setReferenceCounted(false);
5399 }
5400
5401 @Override
5402 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
5403 if (mPolicy.preprocessInputEventTq(event)) {
5404 return true;
5405 }
Romain Guy06882f82009-06-10 13:36:04 -07005406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005407 switch (event.type) {
5408 case RawInputEvent.EV_KEY: {
5409 // XXX begin hack
5410 if (DEBUG) {
5411 if (event.keycode == KeyEvent.KEYCODE_G) {
5412 if (event.value != 0) {
5413 // G down
5414 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
5415 }
5416 return false;
5417 }
5418 if (event.keycode == KeyEvent.KEYCODE_D) {
5419 if (event.value != 0) {
5420 //dump();
5421 }
5422 return false;
5423 }
5424 }
5425 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07005426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 boolean screenIsOff = !mPowerManager.screenIsOn();
5428 boolean screenIsDim = !mPowerManager.screenIsBright();
5429 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07005430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005431 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
5432 mPowerManager.goToSleep(event.when);
5433 }
5434
5435 if (screenIsOff) {
5436 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
5437 }
5438 if (screenIsDim) {
5439 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
5440 }
5441 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
5442 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07005443 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005444 }
Romain Guy06882f82009-06-10 13:36:04 -07005445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
5447 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
5448 filterQueue(this);
5449 mKeyWaiter.appSwitchComing();
5450 }
5451 return true;
5452 } else {
5453 return false;
5454 }
5455 }
Romain Guy06882f82009-06-10 13:36:04 -07005456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 case RawInputEvent.EV_REL: {
5458 boolean screenIsOff = !mPowerManager.screenIsOn();
5459 boolean screenIsDim = !mPowerManager.screenIsBright();
5460 if (screenIsOff) {
5461 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
5462 device.classes, event)) {
5463 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
5464 return false;
5465 }
5466 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
5467 }
5468 if (screenIsDim) {
5469 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
5470 }
5471 return true;
5472 }
Romain Guy06882f82009-06-10 13:36:04 -07005473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 case RawInputEvent.EV_ABS: {
5475 boolean screenIsOff = !mPowerManager.screenIsOn();
5476 boolean screenIsDim = !mPowerManager.screenIsBright();
5477 if (screenIsOff) {
5478 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
5479 device.classes, event)) {
5480 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
5481 return false;
5482 }
5483 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
5484 }
5485 if (screenIsDim) {
5486 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
5487 }
5488 return true;
5489 }
Romain Guy06882f82009-06-10 13:36:04 -07005490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 default:
5492 return true;
5493 }
5494 }
5495
5496 public int filterEvent(QueuedEvent ev) {
5497 switch (ev.classType) {
5498 case RawInputEvent.CLASS_KEYBOARD:
5499 KeyEvent ke = (KeyEvent)ev.event;
5500 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
5501 Log.w(TAG, "Dropping movement key during app switch: "
5502 + ke.getKeyCode() + ", action=" + ke.getAction());
5503 return FILTER_REMOVE;
5504 }
5505 return FILTER_ABORT;
5506 default:
5507 return FILTER_KEEP;
5508 }
5509 }
Romain Guy06882f82009-06-10 13:36:04 -07005510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 /**
5512 * Must be called with the main window manager lock held.
5513 */
5514 void setHoldScreenLocked(boolean holding) {
5515 boolean state = mHoldingScreen.isHeld();
5516 if (holding != state) {
5517 if (holding) {
5518 mHoldingScreen.acquire();
5519 } else {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07005520 mPolicy.screenOnStoppedLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 mHoldingScreen.release();
5522 }
5523 }
5524 }
Michael Chan53071d62009-05-13 17:29:48 -07005525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526
5527 public boolean detectSafeMode() {
5528 mSafeMode = mPolicy.detectSafeMode();
5529 return mSafeMode;
5530 }
Romain Guy06882f82009-06-10 13:36:04 -07005531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 public void systemReady() {
5533 mPolicy.systemReady();
5534 }
Romain Guy06882f82009-06-10 13:36:04 -07005535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 private final class InputDispatcherThread extends Thread {
5537 // Time to wait when there is nothing to do: 9999 seconds.
5538 static final int LONG_WAIT=9999*1000;
5539
5540 public InputDispatcherThread() {
5541 super("InputDispatcher");
5542 }
Romain Guy06882f82009-06-10 13:36:04 -07005543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 @Override
5545 public void run() {
5546 while (true) {
5547 try {
5548 process();
5549 } catch (Exception e) {
5550 Log.e(TAG, "Exception in input dispatcher", e);
5551 }
5552 }
5553 }
Romain Guy06882f82009-06-10 13:36:04 -07005554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 private void process() {
5556 android.os.Process.setThreadPriority(
5557 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07005558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 // The last key event we saw
5560 KeyEvent lastKey = null;
5561
5562 // Last keydown time for auto-repeating keys
5563 long lastKeyTime = SystemClock.uptimeMillis();
5564 long nextKeyTime = lastKeyTime+LONG_WAIT;
5565
Romain Guy06882f82009-06-10 13:36:04 -07005566 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 int keyRepeatCount = 0;
5568
5569 // Need to report that configuration has changed?
5570 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07005571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 while (true) {
5573 long curTime = SystemClock.uptimeMillis();
5574
5575 if (DEBUG_INPUT) Log.v(
5576 TAG, "Waiting for next key: now=" + curTime
5577 + ", repeat @ " + nextKeyTime);
5578
5579 // Retrieve next event, waiting only as long as the next
5580 // repeat timeout. If the configuration has changed, then
5581 // don't wait at all -- we'll report the change as soon as
5582 // we have processed all events.
5583 QueuedEvent ev = mQueue.getEvent(
5584 (int)((!configChanged && curTime < nextKeyTime)
5585 ? (nextKeyTime-curTime) : 0));
5586
5587 if (DEBUG_INPUT && ev != null) Log.v(
5588 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
5589
Michael Chan53071d62009-05-13 17:29:48 -07005590 if (MEASURE_LATENCY) {
5591 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
5592 }
5593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 try {
5595 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07005596 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 int eventType;
5598 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
5599 eventType = eventType((MotionEvent)ev.event);
5600 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
5601 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
5602 eventType = LocalPowerManager.BUTTON_EVENT;
5603 } else {
5604 eventType = LocalPowerManager.OTHER_EVENT;
5605 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07005606 try {
Michael Chan53071d62009-05-13 17:29:48 -07005607 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07005608 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07005609 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07005610 mBatteryStats.noteInputEvent();
5611 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07005612 } catch (RemoteException e) {
5613 // Ignore
5614 }
Michael Chane10de972009-05-18 11:24:50 -07005615
5616 if (eventType != TOUCH_EVENT
5617 && eventType != LONG_TOUCH_EVENT
5618 && eventType != CHEEK_EVENT) {
5619 mPowerManager.userActivity(curTime, false,
5620 eventType, false);
5621 } else if (mLastTouchEventType != eventType
5622 || (curTime - mLastUserActivityCallTime)
5623 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
5624 mLastUserActivityCallTime = curTime;
5625 mLastTouchEventType = eventType;
5626 mPowerManager.userActivity(curTime, false,
5627 eventType, false);
5628 }
5629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 switch (ev.classType) {
5631 case RawInputEvent.CLASS_KEYBOARD:
5632 KeyEvent ke = (KeyEvent)ev.event;
5633 if (ke.isDown()) {
5634 lastKey = ke;
5635 keyRepeatCount = 0;
5636 lastKeyTime = curTime;
5637 nextKeyTime = lastKeyTime
5638 + KEY_REPEAT_FIRST_DELAY;
5639 if (DEBUG_INPUT) Log.v(
5640 TAG, "Received key down: first repeat @ "
5641 + nextKeyTime);
5642 } else {
5643 lastKey = null;
5644 // Arbitrary long timeout.
5645 lastKeyTime = curTime;
5646 nextKeyTime = curTime + LONG_WAIT;
5647 if (DEBUG_INPUT) Log.v(
5648 TAG, "Received key up: ignore repeat @ "
5649 + nextKeyTime);
5650 }
5651 dispatchKey((KeyEvent)ev.event, 0, 0);
5652 mQueue.recycleEvent(ev);
5653 break;
5654 case RawInputEvent.CLASS_TOUCHSCREEN:
5655 //Log.i(TAG, "Read next event " + ev);
5656 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
5657 break;
5658 case RawInputEvent.CLASS_TRACKBALL:
5659 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
5660 break;
5661 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
5662 configChanged = true;
5663 break;
5664 default:
5665 mQueue.recycleEvent(ev);
5666 break;
5667 }
Romain Guy06882f82009-06-10 13:36:04 -07005668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 } else if (configChanged) {
5670 configChanged = false;
5671 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07005672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 } else if (lastKey != null) {
5674 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07005675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 // Timeout occurred while key was down. If it is at or
5677 // past the key repeat time, dispatch the repeat.
5678 if (DEBUG_INPUT) Log.v(
5679 TAG, "Key timeout: repeat=" + nextKeyTime
5680 + ", now=" + curTime);
5681 if (curTime < nextKeyTime) {
5682 continue;
5683 }
Romain Guy06882f82009-06-10 13:36:04 -07005684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 lastKeyTime = nextKeyTime;
5686 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
5687 keyRepeatCount++;
5688 if (DEBUG_INPUT) Log.v(
5689 TAG, "Key repeat: count=" + keyRepeatCount
5690 + ", next @ " + nextKeyTime);
The Android Open Source Project10592532009-03-18 17:39:46 -07005691 dispatchKey(KeyEvent.changeTimeRepeat(lastKey, curTime, keyRepeatCount), 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07005692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 } else {
5694 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07005695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 lastKeyTime = curTime;
5697 nextKeyTime = curTime + LONG_WAIT;
5698 }
Romain Guy06882f82009-06-10 13:36:04 -07005699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 } catch (Exception e) {
5701 Log.e(TAG,
5702 "Input thread received uncaught exception: " + e, e);
5703 }
5704 }
5705 }
5706 }
5707
5708 // -------------------------------------------------------------
5709 // Client Session State
5710 // -------------------------------------------------------------
5711
5712 private final class Session extends IWindowSession.Stub
5713 implements IBinder.DeathRecipient {
5714 final IInputMethodClient mClient;
5715 final IInputContext mInputContext;
5716 final int mUid;
5717 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005718 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 SurfaceSession mSurfaceSession;
5720 int mNumWindow = 0;
5721 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07005722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 /**
5724 * Current pointer move event being dispatched to client window... must
5725 * hold key lock to access.
5726 */
5727 QueuedEvent mPendingPointerMove;
5728 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07005729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 /**
5731 * Current trackball move event being dispatched to client window... must
5732 * hold key lock to access.
5733 */
5734 QueuedEvent mPendingTrackballMove;
5735 WindowState mPendingTrackballWindow;
5736
5737 public Session(IInputMethodClient client, IInputContext inputContext) {
5738 mClient = client;
5739 mInputContext = inputContext;
5740 mUid = Binder.getCallingUid();
5741 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005742 StringBuilder sb = new StringBuilder();
5743 sb.append("Session{");
5744 sb.append(Integer.toHexString(System.identityHashCode(this)));
5745 sb.append(" uid ");
5746 sb.append(mUid);
5747 sb.append("}");
5748 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07005749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 synchronized (mWindowMap) {
5751 if (mInputMethodManager == null && mHaveInputMethods) {
5752 IBinder b = ServiceManager.getService(
5753 Context.INPUT_METHOD_SERVICE);
5754 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
5755 }
5756 }
5757 long ident = Binder.clearCallingIdentity();
5758 try {
5759 // Note: it is safe to call in to the input method manager
5760 // here because we are not holding our lock.
5761 if (mInputMethodManager != null) {
5762 mInputMethodManager.addClient(client, inputContext,
5763 mUid, mPid);
5764 } else {
5765 client.setUsingInputMethod(false);
5766 }
5767 client.asBinder().linkToDeath(this, 0);
5768 } catch (RemoteException e) {
5769 // The caller has died, so we can just forget about this.
5770 try {
5771 if (mInputMethodManager != null) {
5772 mInputMethodManager.removeClient(client);
5773 }
5774 } catch (RemoteException ee) {
5775 }
5776 } finally {
5777 Binder.restoreCallingIdentity(ident);
5778 }
5779 }
Romain Guy06882f82009-06-10 13:36:04 -07005780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 @Override
5782 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
5783 throws RemoteException {
5784 try {
5785 return super.onTransact(code, data, reply, flags);
5786 } catch (RuntimeException e) {
5787 // Log all 'real' exceptions thrown to the caller
5788 if (!(e instanceof SecurityException)) {
5789 Log.e(TAG, "Window Session Crash", e);
5790 }
5791 throw e;
5792 }
5793 }
5794
5795 public void binderDied() {
5796 // Note: it is safe to call in to the input method manager
5797 // here because we are not holding our lock.
5798 try {
5799 if (mInputMethodManager != null) {
5800 mInputMethodManager.removeClient(mClient);
5801 }
5802 } catch (RemoteException e) {
5803 }
5804 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07005805 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 mClientDead = true;
5807 killSessionLocked();
5808 }
5809 }
5810
5811 public int add(IWindow window, WindowManager.LayoutParams attrs,
5812 int viewVisibility, Rect outContentInsets) {
5813 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
5814 }
Romain Guy06882f82009-06-10 13:36:04 -07005815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 public void remove(IWindow window) {
5817 removeWindow(this, window);
5818 }
Romain Guy06882f82009-06-10 13:36:04 -07005819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
5821 int requestedWidth, int requestedHeight, int viewFlags,
5822 boolean insetsPending, Rect outFrame, Rect outContentInsets,
5823 Rect outVisibleInsets, Surface outSurface) {
5824 return relayoutWindow(this, window, attrs,
5825 requestedWidth, requestedHeight, viewFlags, insetsPending,
5826 outFrame, outContentInsets, outVisibleInsets, outSurface);
5827 }
Romain Guy06882f82009-06-10 13:36:04 -07005828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 public void setTransparentRegion(IWindow window, Region region) {
5830 setTransparentRegionWindow(this, window, region);
5831 }
Romain Guy06882f82009-06-10 13:36:04 -07005832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 public void setInsets(IWindow window, int touchableInsets,
5834 Rect contentInsets, Rect visibleInsets) {
5835 setInsetsWindow(this, window, touchableInsets, contentInsets,
5836 visibleInsets);
5837 }
Romain Guy06882f82009-06-10 13:36:04 -07005838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
5840 getWindowDisplayFrame(this, window, outDisplayFrame);
5841 }
Romain Guy06882f82009-06-10 13:36:04 -07005842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 public void finishDrawing(IWindow window) {
5844 if (localLOGV) Log.v(
5845 TAG, "IWindow finishDrawing called for " + window);
5846 finishDrawingWindow(this, window);
5847 }
5848
5849 public void finishKey(IWindow window) {
5850 if (localLOGV) Log.v(
5851 TAG, "IWindow finishKey called for " + window);
5852 mKeyWaiter.finishedKey(this, window, false,
5853 KeyWaiter.RETURN_NOTHING);
5854 }
5855
5856 public MotionEvent getPendingPointerMove(IWindow window) {
5857 if (localLOGV) Log.v(
5858 TAG, "IWindow getPendingMotionEvent called for " + window);
5859 return mKeyWaiter.finishedKey(this, window, false,
5860 KeyWaiter.RETURN_PENDING_POINTER);
5861 }
Romain Guy06882f82009-06-10 13:36:04 -07005862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 public MotionEvent getPendingTrackballMove(IWindow window) {
5864 if (localLOGV) Log.v(
5865 TAG, "IWindow getPendingMotionEvent called for " + window);
5866 return mKeyWaiter.finishedKey(this, window, false,
5867 KeyWaiter.RETURN_PENDING_TRACKBALL);
5868 }
5869
5870 public void setInTouchMode(boolean mode) {
5871 synchronized(mWindowMap) {
5872 mInTouchMode = mode;
5873 }
5874 }
5875
5876 public boolean getInTouchMode() {
5877 synchronized(mWindowMap) {
5878 return mInTouchMode;
5879 }
5880 }
5881
5882 public boolean performHapticFeedback(IWindow window, int effectId,
5883 boolean always) {
5884 synchronized(mWindowMap) {
5885 long ident = Binder.clearCallingIdentity();
5886 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07005887 return mPolicy.performHapticFeedbackLw(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 windowForClientLocked(this, window), effectId, always);
5889 } finally {
5890 Binder.restoreCallingIdentity(ident);
5891 }
5892 }
5893 }
Romain Guy06882f82009-06-10 13:36:04 -07005894
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07005895 public void setWallpaperPosition(IBinder window, float x, float y) {
5896 synchronized(mWindowMap) {
5897 long ident = Binder.clearCallingIdentity();
5898 try {
5899 setWindowWallpaperPositionLocked(windowForClientLocked(this, window),
5900 x, y);
5901 } finally {
5902 Binder.restoreCallingIdentity(ident);
5903 }
5904 }
5905 }
5906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 void windowAddedLocked() {
5908 if (mSurfaceSession == null) {
5909 if (localLOGV) Log.v(
5910 TAG, "First window added to " + this + ", creating SurfaceSession");
5911 mSurfaceSession = new SurfaceSession();
5912 mSessions.add(this);
5913 }
5914 mNumWindow++;
5915 }
5916
5917 void windowRemovedLocked() {
5918 mNumWindow--;
5919 killSessionLocked();
5920 }
Romain Guy06882f82009-06-10 13:36:04 -07005921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 void killSessionLocked() {
5923 if (mNumWindow <= 0 && mClientDead) {
5924 mSessions.remove(this);
5925 if (mSurfaceSession != null) {
5926 if (localLOGV) Log.v(
5927 TAG, "Last window removed from " + this
5928 + ", destroying " + mSurfaceSession);
5929 try {
5930 mSurfaceSession.kill();
5931 } catch (Exception e) {
5932 Log.w(TAG, "Exception thrown when killing surface session "
5933 + mSurfaceSession + " in session " + this
5934 + ": " + e.toString());
5935 }
5936 mSurfaceSession = null;
5937 }
5938 }
5939 }
Romain Guy06882f82009-06-10 13:36:04 -07005940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005942 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
5943 pw.print(" mClientDead="); pw.print(mClientDead);
5944 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
5945 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
5946 pw.print(prefix);
5947 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
5948 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
5949 }
5950 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
5951 pw.print(prefix);
5952 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
5953 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
5954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 }
5956
5957 @Override
5958 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005959 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 }
5961 }
5962
5963 // -------------------------------------------------------------
5964 // Client Window State
5965 // -------------------------------------------------------------
5966
5967 private final class WindowState implements WindowManagerPolicy.WindowState {
5968 final Session mSession;
5969 final IWindow mClient;
5970 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07005971 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 AppWindowToken mAppToken;
5973 AppWindowToken mTargetAppToken;
5974 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
5975 final DeathRecipient mDeathRecipient;
5976 final WindowState mAttachedWindow;
5977 final ArrayList mChildWindows = new ArrayList();
5978 final int mBaseLayer;
5979 final int mSubLayer;
5980 final boolean mLayoutAttached;
5981 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07005982 final boolean mIsWallpaper;
5983 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 int mViewVisibility;
5985 boolean mPolicyVisibility = true;
5986 boolean mPolicyVisibilityAfterAnim = true;
5987 boolean mAppFreezing;
5988 Surface mSurface;
5989 boolean mAttachedHidden; // is our parent window hidden?
5990 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07005991 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005992 int mRequestedWidth;
5993 int mRequestedHeight;
5994 int mLastRequestedWidth;
5995 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 int mLayer;
5997 int mAnimLayer;
5998 int mLastLayer;
5999 boolean mHaveFrame;
6000
6001 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07006002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 // Actual frame shown on-screen (may be modified by animation)
6004 final Rect mShownFrame = new Rect();
6005 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006006
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006007 /**
6008 * Insets that determine the actually visible area
6009 */
6010 final Rect mVisibleInsets = new Rect();
6011 final Rect mLastVisibleInsets = new Rect();
6012 boolean mVisibleInsetsChanged;
6013
6014 /**
6015 * Insets that are covered by system windows
6016 */
6017 final Rect mContentInsets = new Rect();
6018 final Rect mLastContentInsets = new Rect();
6019 boolean mContentInsetsChanged;
6020
6021 /**
6022 * Set to true if we are waiting for this window to receive its
6023 * given internal insets before laying out other windows based on it.
6024 */
6025 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07006026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 /**
6028 * These are the content insets that were given during layout for
6029 * this window, to be applied to windows behind it.
6030 */
6031 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 /**
6034 * These are the visible insets that were given during layout for
6035 * this window, to be applied to windows behind it.
6036 */
6037 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 /**
6040 * Flag indicating whether the touchable region should be adjusted by
6041 * the visible insets; if false the area outside the visible insets is
6042 * NOT touchable, so we must use those to adjust the frame during hit
6043 * tests.
6044 */
6045 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07006046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 // Current transformation being applied.
6048 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
6049 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
6050 float mHScale=1, mVScale=1;
6051 float mLastHScale=1, mLastVScale=1;
6052 final Matrix mTmpMatrix = new Matrix();
6053
6054 // "Real" frame that the application sees.
6055 final Rect mFrame = new Rect();
6056 final Rect mLastFrame = new Rect();
6057
6058 final Rect mContainingFrame = new Rect();
6059 final Rect mDisplayFrame = new Rect();
6060 final Rect mContentFrame = new Rect();
6061 final Rect mVisibleFrame = new Rect();
6062
6063 float mShownAlpha = 1;
6064 float mAlpha = 1;
6065 float mLastAlpha = 1;
6066
6067 // Set to true if, when the window gets displayed, it should perform
6068 // an enter animation.
6069 boolean mEnterAnimationPending;
6070
6071 // Currently running animation.
6072 boolean mAnimating;
6073 boolean mLocalAnimating;
6074 Animation mAnimation;
6075 boolean mAnimationIsEntrance;
6076 boolean mHasTransformation;
6077 boolean mHasLocalTransformation;
6078 final Transformation mTransformation = new Transformation();
6079
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07006080 // If a window showing a wallpaper: the requested offset for the
6081 // wallpaper; if a wallpaper window: the currently applied offset.
6082 float mWallpaperX = -1;
6083 float mWallpaperY = -1;
6084
6085 // Wallpaper windows: pixels offset based on above variables.
6086 int mXOffset;
6087 int mYOffset;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 // This is set after IWindowSession.relayout() has been called at
6090 // least once for the window. It allows us to detect the situation
6091 // where we don't yet have a surface, but should have one soon, so
6092 // we can give the window focus before waiting for the relayout.
6093 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07006094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006095 // This is set after the Surface has been created but before the
6096 // window has been drawn. During this time the surface is hidden.
6097 boolean mDrawPending;
6098
6099 // This is set after the window has finished drawing for the first
6100 // time but before its surface is shown. The surface will be
6101 // displayed when the next layout is run.
6102 boolean mCommitDrawPending;
6103
6104 // This is set during the time after the window's drawing has been
6105 // committed, and before its surface is actually shown. It is used
6106 // to delay showing the surface until all windows in a token are ready
6107 // to be shown.
6108 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07006109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110 // Set when the window has been shown in the screen the first time.
6111 boolean mHasDrawn;
6112
6113 // Currently running an exit animation?
6114 boolean mExiting;
6115
6116 // Currently on the mDestroySurface list?
6117 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07006118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 // Completely remove from window manager after exit animation?
6120 boolean mRemoveOnExit;
6121
6122 // Set when the orientation is changing and this window has not yet
6123 // been updated for the new orientation.
6124 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07006125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006126 // Is this window now (or just being) removed?
6127 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07006128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 WindowState(Session s, IWindow c, WindowToken token,
6130 WindowState attachedWindow, WindowManager.LayoutParams a,
6131 int viewVisibility) {
6132 mSession = s;
6133 mClient = c;
6134 mToken = token;
6135 mAttrs.copyFrom(a);
6136 mViewVisibility = viewVisibility;
6137 DeathRecipient deathRecipient = new DeathRecipient();
6138 mAlpha = a.alpha;
6139 if (localLOGV) Log.v(
6140 TAG, "Window " + this + " client=" + c.asBinder()
6141 + " token=" + token + " (" + mAttrs.token + ")");
6142 try {
6143 c.asBinder().linkToDeath(deathRecipient, 0);
6144 } catch (RemoteException e) {
6145 mDeathRecipient = null;
6146 mAttachedWindow = null;
6147 mLayoutAttached = false;
6148 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006149 mIsWallpaper = false;
6150 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 mBaseLayer = 0;
6152 mSubLayer = 0;
6153 return;
6154 }
6155 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07006156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006157 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
6158 mAttrs.type <= LAST_SUB_WINDOW)) {
6159 // The multiplier here is to reserve space for multiple
6160 // windows in the same type layer.
6161 mBaseLayer = mPolicy.windowTypeToLayerLw(
6162 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
6163 + TYPE_LAYER_OFFSET;
6164 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
6165 mAttachedWindow = attachedWindow;
6166 mAttachedWindow.mChildWindows.add(this);
6167 mLayoutAttached = mAttrs.type !=
6168 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
6169 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
6170 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006171 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
6172 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 } else {
6174 // The multiplier here is to reserve space for multiple
6175 // windows in the same type layer.
6176 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
6177 * TYPE_LAYER_MULTIPLIER
6178 + TYPE_LAYER_OFFSET;
6179 mSubLayer = 0;
6180 mAttachedWindow = null;
6181 mLayoutAttached = false;
6182 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
6183 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006184 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
6185 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 }
6187
6188 WindowState appWin = this;
6189 while (appWin.mAttachedWindow != null) {
6190 appWin = mAttachedWindow;
6191 }
6192 WindowToken appToken = appWin.mToken;
6193 while (appToken.appWindowToken == null) {
6194 WindowToken parent = mTokenMap.get(appToken.token);
6195 if (parent == null || appToken == parent) {
6196 break;
6197 }
6198 appToken = parent;
6199 }
The Android Open Source Project10592532009-03-18 17:39:46 -07006200 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 mAppToken = appToken.appWindowToken;
6202
6203 mSurface = null;
6204 mRequestedWidth = 0;
6205 mRequestedHeight = 0;
6206 mLastRequestedWidth = 0;
6207 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006208 mXOffset = 0;
6209 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 mLayer = 0;
6211 mAnimLayer = 0;
6212 mLastLayer = 0;
6213 }
6214
6215 void attach() {
6216 if (localLOGV) Log.v(
6217 TAG, "Attaching " + this + " token=" + mToken
6218 + ", list=" + mToken.windows);
6219 mSession.windowAddedLocked();
6220 }
6221
6222 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
6223 mHaveFrame = true;
6224
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006225 final Rect container = mContainingFrame;
6226 container.set(pf);
6227
6228 final Rect display = mDisplayFrame;
6229 display.set(df);
6230
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07006231 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006232 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07006233 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
6234 display.intersect(mCompatibleScreenFrame);
6235 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006236 }
6237
6238 final int pw = container.right - container.left;
6239 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240
6241 int w,h;
6242 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
6243 w = mAttrs.width < 0 ? pw : mAttrs.width;
6244 h = mAttrs.height< 0 ? ph : mAttrs.height;
6245 } else {
6246 w = mAttrs.width == mAttrs.FILL_PARENT ? pw : mRequestedWidth;
6247 h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight;
6248 }
Romain Guy06882f82009-06-10 13:36:04 -07006249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250 final Rect content = mContentFrame;
6251 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07006252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 final Rect visible = mVisibleFrame;
6254 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07006255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 final Rect frame = mFrame;
Romain Guy06882f82009-06-10 13:36:04 -07006257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 //System.out.println("In: w=" + w + " h=" + h + " container=" +
6259 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
6260
6261 Gravity.apply(mAttrs.gravity, w, h, container,
6262 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
6263 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
6264
6265 //System.out.println("Out: " + mFrame);
6266
6267 // Now make sure the window fits in the overall display.
6268 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 // Make sure the content and visible frames are inside of the
6271 // final window frame.
6272 if (content.left < frame.left) content.left = frame.left;
6273 if (content.top < frame.top) content.top = frame.top;
6274 if (content.right > frame.right) content.right = frame.right;
6275 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
6276 if (visible.left < frame.left) visible.left = frame.left;
6277 if (visible.top < frame.top) visible.top = frame.top;
6278 if (visible.right > frame.right) visible.right = frame.right;
6279 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07006280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 final Rect contentInsets = mContentInsets;
6282 contentInsets.left = content.left-frame.left;
6283 contentInsets.top = content.top-frame.top;
6284 contentInsets.right = frame.right-content.right;
6285 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07006286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 final Rect visibleInsets = mVisibleInsets;
6288 visibleInsets.left = visible.left-frame.left;
6289 visibleInsets.top = visible.top-frame.top;
6290 visibleInsets.right = frame.right-visible.right;
6291 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07006292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 if (localLOGV) {
6294 //if ("com.google.android.youtube".equals(mAttrs.packageName)
6295 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
6296 Log.v(TAG, "Resolving (mRequestedWidth="
6297 + mRequestedWidth + ", mRequestedheight="
6298 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
6299 + "): frame=" + mFrame.toShortString()
6300 + " ci=" + contentInsets.toShortString()
6301 + " vi=" + visibleInsets.toShortString());
6302 //}
6303 }
6304 }
Romain Guy06882f82009-06-10 13:36:04 -07006305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 public Rect getFrameLw() {
6307 return mFrame;
6308 }
6309
6310 public Rect getShownFrameLw() {
6311 return mShownFrame;
6312 }
6313
6314 public Rect getDisplayFrameLw() {
6315 return mDisplayFrame;
6316 }
6317
6318 public Rect getContentFrameLw() {
6319 return mContentFrame;
6320 }
6321
6322 public Rect getVisibleFrameLw() {
6323 return mVisibleFrame;
6324 }
6325
6326 public boolean getGivenInsetsPendingLw() {
6327 return mGivenInsetsPending;
6328 }
6329
6330 public Rect getGivenContentInsetsLw() {
6331 return mGivenContentInsets;
6332 }
Romain Guy06882f82009-06-10 13:36:04 -07006333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 public Rect getGivenVisibleInsetsLw() {
6335 return mGivenVisibleInsets;
6336 }
Romain Guy06882f82009-06-10 13:36:04 -07006337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006338 public WindowManager.LayoutParams getAttrs() {
6339 return mAttrs;
6340 }
6341
6342 public int getSurfaceLayer() {
6343 return mLayer;
6344 }
Romain Guy06882f82009-06-10 13:36:04 -07006345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 public IApplicationToken getAppToken() {
6347 return mAppToken != null ? mAppToken.appToken : null;
6348 }
6349
6350 public boolean hasAppShownWindows() {
6351 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
6352 }
6353
6354 public boolean hasAppStartingIcon() {
6355 return mAppToken != null ? (mAppToken.startingData != null) : false;
6356 }
6357
6358 public WindowManagerPolicy.WindowState getAppStartingWindow() {
6359 return mAppToken != null ? mAppToken.startingWindow : null;
6360 }
6361
6362 public void setAnimation(Animation anim) {
6363 if (localLOGV) Log.v(
6364 TAG, "Setting animation in " + this + ": " + anim);
6365 mAnimating = false;
6366 mLocalAnimating = false;
6367 mAnimation = anim;
6368 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
6369 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
6370 }
6371
6372 public void clearAnimation() {
6373 if (mAnimation != null) {
6374 mAnimating = true;
6375 mLocalAnimating = false;
6376 mAnimation = null;
6377 }
6378 }
Romain Guy06882f82009-06-10 13:36:04 -07006379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 Surface createSurfaceLocked() {
6381 if (mSurface == null) {
6382 mDrawPending = true;
6383 mCommitDrawPending = false;
6384 mReadyToShow = false;
6385 if (mAppToken != null) {
6386 mAppToken.allDrawn = false;
6387 }
6388
6389 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07006390 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 flags |= Surface.PUSH_BUFFERS;
6392 }
6393
6394 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
6395 flags |= Surface.SECURE;
6396 }
6397 if (DEBUG_VISIBILITY) Log.v(
6398 TAG, "Creating surface in session "
6399 + mSession.mSurfaceSession + " window " + this
6400 + " w=" + mFrame.width()
6401 + " h=" + mFrame.height() + " format="
6402 + mAttrs.format + " flags=" + flags);
6403
6404 int w = mFrame.width();
6405 int h = mFrame.height();
6406 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
6407 // for a scaled surface, we always want the requested
6408 // size.
6409 w = mRequestedWidth;
6410 h = mRequestedHeight;
6411 }
6412
6413 try {
6414 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07006415 mSession.mSurfaceSession, mSession.mPid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 0, w, h, mAttrs.format, flags);
6417 } catch (Surface.OutOfResourcesException e) {
6418 Log.w(TAG, "OutOfResourcesException creating surface");
6419 reclaimSomeSurfaceMemoryLocked(this, "create");
6420 return null;
6421 } catch (Exception e) {
6422 Log.e(TAG, "Exception creating surface", e);
6423 return null;
6424 }
Romain Guy06882f82009-06-10 13:36:04 -07006425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 if (localLOGV) Log.v(
6427 TAG, "Got surface: " + mSurface
6428 + ", set left=" + mFrame.left + " top=" + mFrame.top
6429 + ", animLayer=" + mAnimLayer);
6430 if (SHOW_TRANSACTIONS) {
6431 Log.i(TAG, ">>> OPEN TRANSACTION");
6432 Log.i(TAG, " SURFACE " + mSurface + ": CREATE ("
6433 + mAttrs.getTitle() + ") pos=(" +
6434 mFrame.left + "," + mFrame.top + ") (" +
6435 mFrame.width() + "x" + mFrame.height() + "), layer=" +
6436 mAnimLayer + " HIDE");
6437 }
6438 Surface.openTransaction();
6439 try {
6440 try {
6441 mSurface.setPosition(mFrame.left, mFrame.top);
6442 mSurface.setLayer(mAnimLayer);
6443 mSurface.hide();
6444 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
6445 mSurface.setFlags(Surface.SURFACE_DITHER,
6446 Surface.SURFACE_DITHER);
6447 }
6448 } catch (RuntimeException e) {
6449 Log.w(TAG, "Error creating surface in " + w, e);
6450 reclaimSomeSurfaceMemoryLocked(this, "create-init");
6451 }
6452 mLastHidden = true;
6453 } finally {
6454 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
6455 Surface.closeTransaction();
6456 }
6457 if (localLOGV) Log.v(
6458 TAG, "Created surface " + this);
6459 }
6460 return mSurface;
6461 }
Romain Guy06882f82009-06-10 13:36:04 -07006462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 void destroySurfaceLocked() {
6464 // Window is no longer on-screen, so can no longer receive
6465 // key events... if we were waiting for it to finish
6466 // handling a key event, the wait is over!
6467 mKeyWaiter.finishedKey(mSession, mClient, true,
6468 KeyWaiter.RETURN_NOTHING);
6469 mKeyWaiter.releasePendingPointerLocked(mSession);
6470 mKeyWaiter.releasePendingTrackballLocked(mSession);
6471
6472 if (mAppToken != null && this == mAppToken.startingWindow) {
6473 mAppToken.startingDisplayed = false;
6474 }
Romain Guy06882f82009-06-10 13:36:04 -07006475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 if (localLOGV) Log.v(
6477 TAG, "Window " + this
6478 + " destroying surface " + mSurface + ", session " + mSession);
6479 if (mSurface != null) {
6480 try {
6481 if (SHOW_TRANSACTIONS) {
6482 RuntimeException ex = new RuntimeException();
6483 ex.fillInStackTrace();
6484 Log.i(TAG, " SURFACE " + mSurface + ": DESTROY ("
6485 + mAttrs.getTitle() + ")", ex);
6486 }
6487 mSurface.clear();
6488 } catch (RuntimeException e) {
6489 Log.w(TAG, "Exception thrown when destroying Window " + this
6490 + " surface " + mSurface + " session " + mSession
6491 + ": " + e.toString());
6492 }
6493 mSurface = null;
6494 mDrawPending = false;
6495 mCommitDrawPending = false;
6496 mReadyToShow = false;
6497
6498 int i = mChildWindows.size();
6499 while (i > 0) {
6500 i--;
6501 WindowState c = (WindowState)mChildWindows.get(i);
6502 c.mAttachedHidden = true;
6503 }
6504 }
6505 }
6506
6507 boolean finishDrawingLocked() {
6508 if (mDrawPending) {
6509 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.v(
6510 TAG, "finishDrawingLocked: " + mSurface);
6511 mCommitDrawPending = true;
6512 mDrawPending = false;
6513 return true;
6514 }
6515 return false;
6516 }
6517
6518 // This must be called while inside a transaction.
6519 void commitFinishDrawingLocked(long currentTime) {
6520 //Log.i(TAG, "commitFinishDrawingLocked: " + mSurface);
6521 if (!mCommitDrawPending) {
6522 return;
6523 }
6524 mCommitDrawPending = false;
6525 mReadyToShow = true;
6526 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
6527 final AppWindowToken atoken = mAppToken;
6528 if (atoken == null || atoken.allDrawn || starting) {
6529 performShowLocked();
6530 }
6531 }
6532
6533 // This must be called while inside a transaction.
6534 boolean performShowLocked() {
6535 if (DEBUG_VISIBILITY) {
6536 RuntimeException e = new RuntimeException();
6537 e.fillInStackTrace();
6538 Log.v(TAG, "performShow on " + this
6539 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
6540 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
6541 }
6542 if (mReadyToShow && isReadyForDisplay()) {
6543 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.i(
6544 TAG, " SURFACE " + mSurface + ": SHOW (performShowLocked)");
6545 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + this
6546 + " during animation: policyVis=" + mPolicyVisibility
6547 + " attHidden=" + mAttachedHidden
6548 + " tok.hiddenRequested="
6549 + (mAppToken != null ? mAppToken.hiddenRequested : false)
6550 + " tok.idden="
6551 + (mAppToken != null ? mAppToken.hidden : false)
6552 + " animating=" + mAnimating
6553 + " tok animating="
6554 + (mAppToken != null ? mAppToken.animating : false));
6555 if (!showSurfaceRobustlyLocked(this)) {
6556 return false;
6557 }
6558 mLastAlpha = -1;
6559 mHasDrawn = true;
6560 mLastHidden = false;
6561 mReadyToShow = false;
6562 enableScreenIfNeededLocked();
6563
6564 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07006565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 int i = mChildWindows.size();
6567 while (i > 0) {
6568 i--;
6569 WindowState c = (WindowState)mChildWindows.get(i);
6570 if (c.mSurface != null && c.mAttachedHidden) {
6571 c.mAttachedHidden = false;
6572 c.performShowLocked();
6573 }
6574 }
Romain Guy06882f82009-06-10 13:36:04 -07006575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 if (mAttrs.type != TYPE_APPLICATION_STARTING
6577 && mAppToken != null) {
6578 mAppToken.firstWindowDrawn = true;
6579 if (mAnimation == null && mAppToken.startingData != null) {
6580 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
6581 + mToken
6582 + ": first real window is shown, no animation");
6583 mFinishedStarting.add(mAppToken);
6584 mH.sendEmptyMessage(H.FINISHED_STARTING);
6585 }
6586 mAppToken.updateReportedVisibilityLocked();
6587 }
6588 }
6589 return true;
6590 }
Romain Guy06882f82009-06-10 13:36:04 -07006591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006592 // This must be called while inside a transaction. Returns true if
6593 // there is more animation to run.
6594 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
6595 if (!mDisplayFrozen) {
6596 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07006597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006598 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
6599 mHasTransformation = true;
6600 mHasLocalTransformation = true;
6601 if (!mLocalAnimating) {
6602 if (DEBUG_ANIM) Log.v(
6603 TAG, "Starting animation in " + this +
6604 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
6605 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
6606 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
6607 mAnimation.setStartTime(currentTime);
6608 mLocalAnimating = true;
6609 mAnimating = true;
6610 }
6611 mTransformation.clear();
6612 final boolean more = mAnimation.getTransformation(
6613 currentTime, mTransformation);
6614 if (DEBUG_ANIM) Log.v(
6615 TAG, "Stepped animation in " + this +
6616 ": more=" + more + ", xform=" + mTransformation);
6617 if (more) {
6618 // we're not done!
6619 return true;
6620 }
6621 if (DEBUG_ANIM) Log.v(
6622 TAG, "Finished animation in " + this +
6623 " @ " + currentTime);
6624 mAnimation = null;
6625 //WindowManagerService.this.dump();
6626 }
6627 mHasLocalTransformation = false;
6628 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
6629 && mAppToken.hasTransformation) {
6630 // When our app token is animating, we kind-of pretend like
6631 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
6632 // part of this check means that we will only do this if
6633 // our window is not currently exiting, or it is not
6634 // locally animating itself. The idea being that one that
6635 // is exiting and doing a local animation should be removed
6636 // once that animation is done.
6637 mAnimating = true;
6638 mHasTransformation = true;
6639 mTransformation.clear();
6640 return false;
6641 } else if (mHasTransformation) {
6642 // Little trick to get through the path below to act like
6643 // we have finished an animation.
6644 mAnimating = true;
6645 } else if (isAnimating()) {
6646 mAnimating = true;
6647 }
6648 } else if (mAnimation != null) {
6649 // If the display is frozen, and there is a pending animation,
6650 // clear it and make sure we run the cleanup code.
6651 mAnimating = true;
6652 mLocalAnimating = true;
6653 mAnimation = null;
6654 }
Romain Guy06882f82009-06-10 13:36:04 -07006655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 if (!mAnimating && !mLocalAnimating) {
6657 return false;
6658 }
6659
6660 if (DEBUG_ANIM) Log.v(
6661 TAG, "Animation done in " + this + ": exiting=" + mExiting
6662 + ", reportedVisible="
6663 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07006664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 mAnimating = false;
6666 mLocalAnimating = false;
6667 mAnimation = null;
6668 mAnimLayer = mLayer;
6669 if (mIsImWindow) {
6670 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07006671 } else if (mIsWallpaper) {
6672 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 }
6674 if (DEBUG_LAYERS) Log.v(TAG, "Stepping win " + this
6675 + " anim layer: " + mAnimLayer);
6676 mHasTransformation = false;
6677 mHasLocalTransformation = false;
6678 mPolicyVisibility = mPolicyVisibilityAfterAnim;
6679 mTransformation.clear();
6680 if (mHasDrawn
6681 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
6682 && mAppToken != null
6683 && mAppToken.firstWindowDrawn
6684 && mAppToken.startingData != null) {
6685 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
6686 + mToken + ": first real window done animating");
6687 mFinishedStarting.add(mAppToken);
6688 mH.sendEmptyMessage(H.FINISHED_STARTING);
6689 }
Romain Guy06882f82009-06-10 13:36:04 -07006690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006691 finishExit();
6692
6693 if (mAppToken != null) {
6694 mAppToken.updateReportedVisibilityLocked();
6695 }
6696
6697 return false;
6698 }
6699
6700 void finishExit() {
6701 if (DEBUG_ANIM) Log.v(
6702 TAG, "finishExit in " + this
6703 + ": exiting=" + mExiting
6704 + " remove=" + mRemoveOnExit
6705 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07006706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 final int N = mChildWindows.size();
6708 for (int i=0; i<N; i++) {
6709 ((WindowState)mChildWindows.get(i)).finishExit();
6710 }
Romain Guy06882f82009-06-10 13:36:04 -07006711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 if (!mExiting) {
6713 return;
6714 }
Romain Guy06882f82009-06-10 13:36:04 -07006715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006716 if (isWindowAnimating()) {
6717 return;
6718 }
6719
6720 if (localLOGV) Log.v(
6721 TAG, "Exit animation finished in " + this
6722 + ": remove=" + mRemoveOnExit);
6723 if (mSurface != null) {
6724 mDestroySurface.add(this);
6725 mDestroying = true;
6726 if (SHOW_TRANSACTIONS) Log.i(
6727 TAG, " SURFACE " + mSurface + ": HIDE (finishExit)");
6728 try {
6729 mSurface.hide();
6730 } catch (RuntimeException e) {
6731 Log.w(TAG, "Error hiding surface in " + this, e);
6732 }
6733 mLastHidden = true;
6734 mKeyWaiter.releasePendingPointerLocked(mSession);
6735 }
6736 mExiting = false;
6737 if (mRemoveOnExit) {
6738 mPendingRemove.add(this);
6739 mRemoveOnExit = false;
6740 }
6741 }
Romain Guy06882f82009-06-10 13:36:04 -07006742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006743 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
6744 if (dsdx < .99999f || dsdx > 1.00001f) return false;
6745 if (dtdy < .99999f || dtdy > 1.00001f) return false;
6746 if (dtdx < -.000001f || dtdx > .000001f) return false;
6747 if (dsdy < -.000001f || dsdy > .000001f) return false;
6748 return true;
6749 }
Romain Guy06882f82009-06-10 13:36:04 -07006750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006751 void computeShownFrameLocked() {
6752 final boolean selfTransformation = mHasLocalTransformation;
6753 Transformation attachedTransformation =
6754 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
6755 ? mAttachedWindow.mTransformation : null;
6756 Transformation appTransformation =
6757 (mAppToken != null && mAppToken.hasTransformation)
6758 ? mAppToken.transformation : null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07006759
6760 // Wallpapers are animated based on the "real" window they
6761 // are currently targeting.
6762 if (mAttrs.type == TYPE_WALLPAPER && mWallpaperTarget != null) {
6763 if (mWallpaperTarget.mHasLocalTransformation) {
6764 attachedTransformation = mWallpaperTarget.mTransformation;
6765 }
6766 if (mWallpaperTarget.mAppToken != null &&
6767 mWallpaperTarget.mAppToken.hasTransformation) {
6768 appTransformation = mWallpaperTarget.mAppToken.transformation;
6769 }
6770 }
6771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 if (selfTransformation || attachedTransformation != null
6773 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07006774 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 final Rect frame = mFrame;
6776 final float tmpFloats[] = mTmpFloats;
6777 final Matrix tmpMatrix = mTmpMatrix;
6778
6779 // Compute the desired transformation.
6780 tmpMatrix.setTranslate(frame.left, frame.top);
6781 if (selfTransformation) {
6782 tmpMatrix.preConcat(mTransformation.getMatrix());
6783 }
6784 if (attachedTransformation != null) {
6785 tmpMatrix.preConcat(attachedTransformation.getMatrix());
6786 }
6787 if (appTransformation != null) {
6788 tmpMatrix.preConcat(appTransformation.getMatrix());
6789 }
6790
6791 // "convert" it into SurfaceFlinger's format
6792 // (a 2x2 matrix + an offset)
6793 // Here we must not transform the position of the surface
6794 // since it is already included in the transformation.
6795 //Log.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07006796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006797 tmpMatrix.getValues(tmpFloats);
6798 mDsDx = tmpFloats[Matrix.MSCALE_X];
6799 mDtDx = tmpFloats[Matrix.MSKEW_X];
6800 mDsDy = tmpFloats[Matrix.MSKEW_Y];
6801 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006802 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
6803 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 int w = frame.width();
6805 int h = frame.height();
6806 mShownFrame.set(x, y, x+w, y+h);
6807
6808 // Now set the alpha... but because our current hardware
6809 // can't do alpha transformation on a non-opaque surface,
6810 // turn it off if we are running an animation that is also
6811 // transforming since it is more important to have that
6812 // animation be smooth.
6813 mShownAlpha = mAlpha;
6814 if (!mLimitedAlphaCompositing
6815 || (!PixelFormat.formatHasAlpha(mAttrs.format)
6816 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
6817 && x == frame.left && y == frame.top))) {
6818 //Log.i(TAG, "Applying alpha transform");
6819 if (selfTransformation) {
6820 mShownAlpha *= mTransformation.getAlpha();
6821 }
6822 if (attachedTransformation != null) {
6823 mShownAlpha *= attachedTransformation.getAlpha();
6824 }
6825 if (appTransformation != null) {
6826 mShownAlpha *= appTransformation.getAlpha();
6827 }
6828 } else {
6829 //Log.i(TAG, "Not applying alpha transform");
6830 }
Romain Guy06882f82009-06-10 13:36:04 -07006831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 if (localLOGV) Log.v(
6833 TAG, "Continuing animation in " + this +
6834 ": " + mShownFrame +
6835 ", alpha=" + mTransformation.getAlpha());
6836 return;
6837 }
Romain Guy06882f82009-06-10 13:36:04 -07006838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006840 if (mXOffset != 0 || mYOffset != 0) {
6841 mShownFrame.offset(mXOffset, mYOffset);
6842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 mShownAlpha = mAlpha;
6844 mDsDx = 1;
6845 mDtDx = 0;
6846 mDsDy = 0;
6847 mDtDy = 1;
6848 }
Romain Guy06882f82009-06-10 13:36:04 -07006849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 /**
6851 * Is this window visible? It is not visible if there is no
6852 * surface, or we are in the process of running an exit animation
6853 * that will remove the surface, or its app token has been hidden.
6854 */
6855 public boolean isVisibleLw() {
6856 final AppWindowToken atoken = mAppToken;
6857 return mSurface != null && mPolicyVisibility && !mAttachedHidden
6858 && (atoken == null || !atoken.hiddenRequested)
6859 && !mExiting && !mDestroying;
6860 }
6861
6862 /**
6863 * Is this window visible, ignoring its app token? It is not visible
6864 * if there is no surface, or we are in the process of running an exit animation
6865 * that will remove the surface.
6866 */
6867 public boolean isWinVisibleLw() {
6868 final AppWindowToken atoken = mAppToken;
6869 return mSurface != null && mPolicyVisibility && !mAttachedHidden
6870 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
6871 && !mExiting && !mDestroying;
6872 }
6873
6874 /**
6875 * The same as isVisible(), but follows the current hidden state of
6876 * the associated app token, not the pending requested hidden state.
6877 */
6878 boolean isVisibleNow() {
6879 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07006880 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 }
6882
6883 /**
6884 * Same as isVisible(), but we also count it as visible between the
6885 * call to IWindowSession.add() and the first relayout().
6886 */
6887 boolean isVisibleOrAdding() {
6888 final AppWindowToken atoken = mAppToken;
6889 return (mSurface != null
6890 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
6891 && mPolicyVisibility && !mAttachedHidden
6892 && (atoken == null || !atoken.hiddenRequested)
6893 && !mExiting && !mDestroying;
6894 }
6895
6896 /**
6897 * Is this window currently on-screen? It is on-screen either if it
6898 * is visible or it is currently running an animation before no longer
6899 * being visible.
6900 */
6901 boolean isOnScreen() {
6902 final AppWindowToken atoken = mAppToken;
6903 if (atoken != null) {
6904 return mSurface != null && mPolicyVisibility && !mDestroying
6905 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07006906 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 } else {
6908 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07006909 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 }
6911 }
Romain Guy06882f82009-06-10 13:36:04 -07006912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 /**
6914 * Like isOnScreen(), but we don't return true if the window is part
6915 * of a transition that has not yet been started.
6916 */
6917 boolean isReadyForDisplay() {
6918 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07006919 final boolean animating = atoken != null
6920 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 return mSurface != null && mPolicyVisibility && !mDestroying
The Android Open Source Project10592532009-03-18 17:39:46 -07006922 && ((!mAttachedHidden && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07006923 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 }
6925
6926 /** Is the window or its container currently animating? */
6927 boolean isAnimating() {
6928 final WindowState attached = mAttachedWindow;
6929 final AppWindowToken atoken = mAppToken;
6930 return mAnimation != null
6931 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07006932 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006933 (atoken.animation != null
6934 || atoken.inPendingTransaction));
6935 }
6936
6937 /** Is this window currently animating? */
6938 boolean isWindowAnimating() {
6939 return mAnimation != null;
6940 }
6941
6942 /**
6943 * Like isOnScreen, but returns false if the surface hasn't yet
6944 * been drawn.
6945 */
6946 public boolean isDisplayedLw() {
6947 final AppWindowToken atoken = mAppToken;
6948 return mSurface != null && mPolicyVisibility && !mDestroying
6949 && !mDrawPending && !mCommitDrawPending
6950 && ((!mAttachedHidden &&
6951 (atoken == null || !atoken.hiddenRequested))
6952 || mAnimating);
6953 }
6954
6955 public boolean fillsScreenLw(int screenWidth, int screenHeight,
6956 boolean shownFrame, boolean onlyOpaque) {
6957 if (mSurface == null) {
6958 return false;
6959 }
6960 if (mAppToken != null && !mAppToken.appFullscreen) {
6961 return false;
6962 }
6963 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
6964 return false;
6965 }
6966 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07006967
6968 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
6969 return frame.left <= mCompatibleScreenFrame.left &&
6970 frame.top <= mCompatibleScreenFrame.top &&
6971 frame.right >= mCompatibleScreenFrame.right &&
6972 frame.bottom >= mCompatibleScreenFrame.bottom;
6973 } else {
6974 return frame.left <= 0 && frame.top <= 0
6975 && frame.right >= screenWidth
6976 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006978 }
Romain Guy06882f82009-06-10 13:36:04 -07006979
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006980 /**
6981 * Return true if the window is opaque and fully drawn.
6982 */
6983 boolean isOpaqueDrawn() {
6984 return mAttrs.format == PixelFormat.OPAQUE && mSurface != null
6985 && mAnimation == null && !mDrawPending && !mCommitDrawPending;
6986 }
6987
6988 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
6989 return
6990 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07006991 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
6992 // only if it's visible
6993 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07006994 // and only if the application fills the compatible screen
6995 mFrame.left <= mCompatibleScreenFrame.left &&
6996 mFrame.top <= mCompatibleScreenFrame.top &&
6997 mFrame.right >= mCompatibleScreenFrame.right &&
6998 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07006999 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007000 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007001 }
7002
7003 boolean isFullscreen(int screenWidth, int screenHeight) {
7004 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007005 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 }
7007
7008 void removeLocked() {
7009 if (mAttachedWindow != null) {
7010 mAttachedWindow.mChildWindows.remove(this);
7011 }
7012 destroySurfaceLocked();
7013 mSession.windowRemovedLocked();
7014 try {
7015 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
7016 } catch (RuntimeException e) {
7017 // Ignore if it has already been removed (usually because
7018 // we are doing this as part of processing a death note.)
7019 }
7020 }
7021
7022 private class DeathRecipient implements IBinder.DeathRecipient {
7023 public void binderDied() {
7024 try {
7025 synchronized(mWindowMap) {
7026 WindowState win = windowForClientLocked(mSession, mClient);
7027 Log.i(TAG, "WIN DEATH: " + win);
7028 if (win != null) {
7029 removeWindowLocked(mSession, win);
7030 }
7031 }
7032 } catch (IllegalArgumentException ex) {
7033 // This will happen if the window has already been
7034 // removed.
7035 }
7036 }
7037 }
7038
7039 /** Returns true if this window desires key events. */
7040 public final boolean canReceiveKeys() {
7041 return isVisibleOrAdding()
7042 && (mViewVisibility == View.VISIBLE)
7043 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
7044 }
7045
7046 public boolean hasDrawnLw() {
7047 return mHasDrawn;
7048 }
7049
7050 public boolean showLw(boolean doAnimation) {
7051 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim) {
7052 mPolicyVisibility = true;
7053 mPolicyVisibilityAfterAnim = true;
7054 if (doAnimation) {
7055 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
7056 }
7057 requestAnimationLocked(0);
7058 return true;
7059 }
7060 return false;
7061 }
7062
7063 public boolean hideLw(boolean doAnimation) {
7064 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
7065 : mPolicyVisibility;
7066 if (current) {
7067 if (doAnimation) {
7068 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
7069 if (mAnimation == null) {
7070 doAnimation = false;
7071 }
7072 }
7073 if (doAnimation) {
7074 mPolicyVisibilityAfterAnim = false;
7075 } else {
7076 mPolicyVisibilityAfterAnim = false;
7077 mPolicyVisibility = false;
7078 }
7079 requestAnimationLocked(0);
7080 return true;
7081 }
7082 return false;
7083 }
7084
7085 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007086 StringBuilder sb = new StringBuilder(64);
Romain Guy06882f82009-06-10 13:36:04 -07007087
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007088 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
7089 pw.print(" mClient="); pw.println(mClient.asBinder());
7090 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
7091 if (mAttachedWindow != null || mLayoutAttached) {
7092 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
7093 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
7094 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007095 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
7096 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
7097 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007098 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
7099 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007100 }
7101 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
7102 pw.print(" mSubLayer="); pw.print(mSubLayer);
7103 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
7104 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
7105 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
7106 pw.print("="); pw.print(mAnimLayer);
7107 pw.print(" mLastLayer="); pw.println(mLastLayer);
7108 if (mSurface != null) {
7109 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
7110 }
7111 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
7112 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
7113 if (mAppToken != null) {
7114 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
7115 }
7116 if (mTargetAppToken != null) {
7117 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
7118 }
7119 pw.print(prefix); pw.print("mViewVisibility=0x");
7120 pw.print(Integer.toHexString(mViewVisibility));
7121 pw.print(" mLastHidden="); pw.print(mLastHidden);
7122 pw.print(" mHaveFrame="); pw.println(mHaveFrame);
7123 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
7124 pw.print(prefix); pw.print("mPolicyVisibility=");
7125 pw.print(mPolicyVisibility);
7126 pw.print(" mPolicyVisibilityAfterAnim=");
7127 pw.print(mPolicyVisibilityAfterAnim);
7128 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
7129 }
7130 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007131 pw.print(" h="); pw.println(mRequestedHeight);
7132 if (mXOffset != 0 || mYOffset != 0) {
7133 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
7134 pw.print(" y="); pw.println(mYOffset);
7135 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007136 pw.print(prefix); pw.print("mGivenContentInsets=");
7137 mGivenContentInsets.printShortString(pw);
7138 pw.print(" mGivenVisibleInsets=");
7139 mGivenVisibleInsets.printShortString(pw);
7140 pw.println();
7141 if (mTouchableInsets != 0 || mGivenInsetsPending) {
7142 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
7143 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
7144 }
7145 pw.print(prefix); pw.print("mShownFrame=");
7146 mShownFrame.printShortString(pw);
7147 pw.print(" last="); mLastShownFrame.printShortString(pw);
7148 pw.println();
7149 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
7150 pw.print(" last="); mLastFrame.printShortString(pw);
7151 pw.println();
7152 pw.print(prefix); pw.print("mContainingFrame=");
7153 mContainingFrame.printShortString(pw);
7154 pw.print(" mDisplayFrame=");
7155 mDisplayFrame.printShortString(pw);
7156 pw.println();
7157 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
7158 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
7159 pw.println();
7160 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
7161 pw.print(" last="); mLastContentInsets.printShortString(pw);
7162 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
7163 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
7164 pw.println();
7165 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
7166 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
7167 pw.print(" mAlpha="); pw.print(mAlpha);
7168 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
7169 }
7170 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
7171 || mAnimation != null) {
7172 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
7173 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
7174 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
7175 pw.print(" mAnimation="); pw.println(mAnimation);
7176 }
7177 if (mHasTransformation || mHasLocalTransformation) {
7178 pw.print(prefix); pw.print("XForm: has=");
7179 pw.print(mHasTransformation);
7180 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
7181 pw.print(" "); mTransformation.printShortString(pw);
7182 pw.println();
7183 }
7184 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
7185 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
7186 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
7187 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
7188 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
7189 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
7190 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
7191 pw.print(" mDestroying="); pw.print(mDestroying);
7192 pw.print(" mRemoved="); pw.println(mRemoved);
7193 }
7194 if (mOrientationChanging || mAppFreezing) {
7195 pw.print(prefix); pw.print("mOrientationChanging=");
7196 pw.print(mOrientationChanging);
7197 pw.print(" mAppFreezing="); pw.println(mAppFreezing);
7198 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07007199 if (mHScale != 1 || mVScale != 1) {
7200 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
7201 pw.print(" mVScale="); pw.println(mVScale);
7202 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007203 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007204 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
7205 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
7206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 }
7208
7209 @Override
7210 public String toString() {
7211 return "Window{"
7212 + Integer.toHexString(System.identityHashCode(this))
7213 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
7214 }
7215 }
Romain Guy06882f82009-06-10 13:36:04 -07007216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 // -------------------------------------------------------------
7218 // Window Token State
7219 // -------------------------------------------------------------
7220
7221 class WindowToken {
7222 // The actual token.
7223 final IBinder token;
7224
7225 // The type of window this token is for, as per WindowManager.LayoutParams.
7226 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07007227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 // Set if this token was explicitly added by a client, so should
7229 // not be removed when all windows are removed.
7230 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07007231
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007232 // For printing.
7233 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07007234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 // If this is an AppWindowToken, this is non-null.
7236 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07007237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007238 // All of the windows associated with this token.
7239 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
7240
7241 // Is key dispatching paused for this token?
7242 boolean paused = false;
7243
7244 // Should this token's windows be hidden?
7245 boolean hidden;
7246
7247 // Temporary for finding which tokens no longer have visible windows.
7248 boolean hasVisible;
7249
7250 WindowToken(IBinder _token, int type, boolean _explicit) {
7251 token = _token;
7252 windowType = type;
7253 explicit = _explicit;
7254 }
7255
7256 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007257 pw.print(prefix); pw.print("token="); pw.println(token);
7258 pw.print(prefix); pw.print("windows="); pw.println(windows);
7259 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
7260 pw.print(" hidden="); pw.print(hidden);
7261 pw.print(" hasVisible="); pw.println(hasVisible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 }
7263
7264 @Override
7265 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007266 if (stringName == null) {
7267 StringBuilder sb = new StringBuilder();
7268 sb.append("WindowToken{");
7269 sb.append(Integer.toHexString(System.identityHashCode(this)));
7270 sb.append(" token="); sb.append(token); sb.append('}');
7271 stringName = sb.toString();
7272 }
7273 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007274 }
7275 };
7276
7277 class AppWindowToken extends WindowToken {
7278 // Non-null only for application tokens.
7279 final IApplicationToken appToken;
7280
7281 // All of the windows and child windows that are included in this
7282 // application token. Note this list is NOT sorted!
7283 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
7284
7285 int groupId = -1;
7286 boolean appFullscreen;
7287 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Romain Guy06882f82009-06-10 13:36:04 -07007288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 // These are used for determining when all windows associated with
7290 // an activity have been drawn, so they can be made visible together
7291 // at the same time.
7292 int lastTransactionSequence = mTransactionSequence-1;
7293 int numInterestingWindows;
7294 int numDrawnWindows;
7295 boolean inPendingTransaction;
7296 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07007297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 // Is this token going to be hidden in a little while? If so, it
7299 // won't be taken into account for setting the screen orientation.
7300 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07007301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 // Is this window's surface needed? This is almost like hidden, except
7303 // it will sometimes be true a little earlier: when the token has
7304 // been shown, but is still waiting for its app transition to execute
7305 // before making its windows shown.
7306 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07007307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 // Have we told the window clients to hide themselves?
7309 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07007310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007311 // Last visibility state we reported to the app token.
7312 boolean reportedVisible;
7313
7314 // Set to true when the token has been removed from the window mgr.
7315 boolean removed;
7316
7317 // Have we been asked to have this token keep the screen frozen?
7318 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07007319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 boolean animating;
7321 Animation animation;
7322 boolean hasTransformation;
7323 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07007324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007325 // Offset to the window of all layers in the token, for use by
7326 // AppWindowToken animations.
7327 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07007328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 // Information about an application starting window if displayed.
7330 StartingData startingData;
7331 WindowState startingWindow;
7332 View startingView;
7333 boolean startingDisplayed;
7334 boolean startingMoved;
7335 boolean firstWindowDrawn;
7336
7337 AppWindowToken(IApplicationToken _token) {
7338 super(_token.asBinder(),
7339 WindowManager.LayoutParams.TYPE_APPLICATION, true);
7340 appWindowToken = this;
7341 appToken = _token;
7342 }
Romain Guy06882f82009-06-10 13:36:04 -07007343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 public void setAnimation(Animation anim) {
7345 if (localLOGV) Log.v(
7346 TAG, "Setting animation in " + this + ": " + anim);
7347 animation = anim;
7348 animating = false;
7349 anim.restrictDuration(MAX_ANIMATION_DURATION);
7350 anim.scaleCurrentDuration(mTransitionAnimationScale);
7351 int zorder = anim.getZAdjustment();
7352 int adj = 0;
7353 if (zorder == Animation.ZORDER_TOP) {
7354 adj = TYPE_LAYER_OFFSET;
7355 } else if (zorder == Animation.ZORDER_BOTTOM) {
7356 adj = -TYPE_LAYER_OFFSET;
7357 }
Romain Guy06882f82009-06-10 13:36:04 -07007358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 if (animLayerAdjustment != adj) {
7360 animLayerAdjustment = adj;
7361 updateLayers();
7362 }
7363 }
Romain Guy06882f82009-06-10 13:36:04 -07007364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 public void setDummyAnimation() {
7366 if (animation == null) {
7367 if (localLOGV) Log.v(
7368 TAG, "Setting dummy animation in " + this);
7369 animation = sDummyAnimation;
7370 }
7371 }
7372
7373 public void clearAnimation() {
7374 if (animation != null) {
7375 animation = null;
7376 animating = true;
7377 }
7378 }
Romain Guy06882f82009-06-10 13:36:04 -07007379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 void updateLayers() {
7381 final int N = allAppWindows.size();
7382 final int adj = animLayerAdjustment;
7383 for (int i=0; i<N; i++) {
7384 WindowState w = allAppWindows.get(i);
7385 w.mAnimLayer = w.mLayer + adj;
7386 if (DEBUG_LAYERS) Log.v(TAG, "Updating layer " + w + ": "
7387 + w.mAnimLayer);
7388 if (w == mInputMethodTarget) {
7389 setInputMethodAnimLayerAdjustment(adj);
7390 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007391 if (w == mWallpaperTarget) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007392 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 }
7395 }
Romain Guy06882f82009-06-10 13:36:04 -07007396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 void sendAppVisibilityToClients() {
7398 final int N = allAppWindows.size();
7399 for (int i=0; i<N; i++) {
7400 WindowState win = allAppWindows.get(i);
7401 if (win == startingWindow && clientHidden) {
7402 // Don't hide the starting window.
7403 continue;
7404 }
7405 try {
7406 if (DEBUG_VISIBILITY) Log.v(TAG,
7407 "Setting visibility of " + win + ": " + (!clientHidden));
7408 win.mClient.dispatchAppVisibility(!clientHidden);
7409 } catch (RemoteException e) {
7410 }
7411 }
7412 }
Romain Guy06882f82009-06-10 13:36:04 -07007413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 void showAllWindowsLocked() {
7415 final int NW = allAppWindows.size();
7416 for (int i=0; i<NW; i++) {
7417 WindowState w = allAppWindows.get(i);
7418 if (DEBUG_VISIBILITY) Log.v(TAG,
7419 "performing show on: " + w);
7420 w.performShowLocked();
7421 }
7422 }
Romain Guy06882f82009-06-10 13:36:04 -07007423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 // This must be called while inside a transaction.
7425 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
7426 if (!mDisplayFrozen) {
7427 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07007428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 if (animation == sDummyAnimation) {
7430 // This guy is going to animate, but not yet. For now count
7431 // it is not animating for purposes of scheduling transactions;
7432 // when it is really time to animate, this will be set to
7433 // a real animation and the next call will execute normally.
7434 return false;
7435 }
Romain Guy06882f82009-06-10 13:36:04 -07007436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437 if ((allDrawn || animating || startingDisplayed) && animation != null) {
7438 if (!animating) {
7439 if (DEBUG_ANIM) Log.v(
7440 TAG, "Starting animation in " + this +
7441 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
7442 + " scale=" + mTransitionAnimationScale
7443 + " allDrawn=" + allDrawn + " animating=" + animating);
7444 animation.initialize(dw, dh, dw, dh);
7445 animation.setStartTime(currentTime);
7446 animating = true;
7447 }
7448 transformation.clear();
7449 final boolean more = animation.getTransformation(
7450 currentTime, transformation);
7451 if (DEBUG_ANIM) Log.v(
7452 TAG, "Stepped animation in " + this +
7453 ": more=" + more + ", xform=" + transformation);
7454 if (more) {
7455 // we're done!
7456 hasTransformation = true;
7457 return true;
7458 }
7459 if (DEBUG_ANIM) Log.v(
7460 TAG, "Finished animation in " + this +
7461 " @ " + currentTime);
7462 animation = null;
7463 }
7464 } else if (animation != null) {
7465 // If the display is frozen, and there is a pending animation,
7466 // clear it and make sure we run the cleanup code.
7467 animating = true;
7468 animation = null;
7469 }
7470
7471 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07007472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 if (!animating) {
7474 return false;
7475 }
7476
7477 clearAnimation();
7478 animating = false;
7479 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
7480 moveInputMethodWindowsIfNeededLocked(true);
7481 }
Romain Guy06882f82009-06-10 13:36:04 -07007482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 if (DEBUG_ANIM) Log.v(
7484 TAG, "Animation done in " + this
7485 + ": reportedVisible=" + reportedVisible);
7486
7487 transformation.clear();
7488 if (animLayerAdjustment != 0) {
7489 animLayerAdjustment = 0;
7490 updateLayers();
7491 }
Romain Guy06882f82009-06-10 13:36:04 -07007492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 final int N = windows.size();
7494 for (int i=0; i<N; i++) {
7495 ((WindowState)windows.get(i)).finishExit();
7496 }
7497 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07007498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 return false;
7500 }
7501
7502 void updateReportedVisibilityLocked() {
7503 if (appToken == null) {
7504 return;
7505 }
Romain Guy06882f82009-06-10 13:36:04 -07007506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007507 int numInteresting = 0;
7508 int numVisible = 0;
7509 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07007510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007511 if (DEBUG_VISIBILITY) Log.v(TAG, "Update reported visibility: " + this);
7512 final int N = allAppWindows.size();
7513 for (int i=0; i<N; i++) {
7514 WindowState win = allAppWindows.get(i);
7515 if (win == startingWindow || win.mAppFreezing) {
7516 continue;
7517 }
7518 if (DEBUG_VISIBILITY) {
7519 Log.v(TAG, "Win " + win + ": isDisplayed="
7520 + win.isDisplayedLw()
7521 + ", isAnimating=" + win.isAnimating());
7522 if (!win.isDisplayedLw()) {
7523 Log.v(TAG, "Not displayed: s=" + win.mSurface
7524 + " pv=" + win.mPolicyVisibility
7525 + " dp=" + win.mDrawPending
7526 + " cdp=" + win.mCommitDrawPending
7527 + " ah=" + win.mAttachedHidden
7528 + " th="
7529 + (win.mAppToken != null
7530 ? win.mAppToken.hiddenRequested : false)
7531 + " a=" + win.mAnimating);
7532 }
7533 }
7534 numInteresting++;
7535 if (win.isDisplayedLw()) {
7536 if (!win.isAnimating()) {
7537 numVisible++;
7538 }
7539 nowGone = false;
7540 } else if (win.isAnimating()) {
7541 nowGone = false;
7542 }
7543 }
Romain Guy06882f82009-06-10 13:36:04 -07007544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
7546 if (DEBUG_VISIBILITY) Log.v(TAG, "VIS " + this + ": interesting="
7547 + numInteresting + " visible=" + numVisible);
7548 if (nowVisible != reportedVisible) {
7549 if (DEBUG_VISIBILITY) Log.v(
7550 TAG, "Visibility changed in " + this
7551 + ": vis=" + nowVisible);
7552 reportedVisible = nowVisible;
7553 Message m = mH.obtainMessage(
7554 H.REPORT_APPLICATION_TOKEN_WINDOWS,
7555 nowVisible ? 1 : 0,
7556 nowGone ? 1 : 0,
7557 this);
7558 mH.sendMessage(m);
7559 }
7560 }
Romain Guy06882f82009-06-10 13:36:04 -07007561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 void dump(PrintWriter pw, String prefix) {
7563 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007564 if (appToken != null) {
7565 pw.print(prefix); pw.println("app=true");
7566 }
7567 if (allAppWindows.size() > 0) {
7568 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
7569 }
7570 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
7571 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
7572 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
7573 pw.print(" clientHidden="); pw.print(clientHidden);
7574 pw.print(" willBeHidden="); pw.print(willBeHidden);
7575 pw.print(" reportedVisible="); pw.println(reportedVisible);
7576 if (paused || freezingScreen) {
7577 pw.print(prefix); pw.print("paused="); pw.print(paused);
7578 pw.print(" freezingScreen="); pw.println(freezingScreen);
7579 }
7580 if (numInterestingWindows != 0 || numDrawnWindows != 0
7581 || inPendingTransaction || allDrawn) {
7582 pw.print(prefix); pw.print("numInterestingWindows=");
7583 pw.print(numInterestingWindows);
7584 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
7585 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
7586 pw.print(" allDrawn="); pw.println(allDrawn);
7587 }
7588 if (animating || animation != null) {
7589 pw.print(prefix); pw.print("animating="); pw.print(animating);
7590 pw.print(" animation="); pw.println(animation);
7591 }
7592 if (animLayerAdjustment != 0) {
7593 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
7594 }
7595 if (hasTransformation) {
7596 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
7597 pw.print(" transformation="); transformation.printShortString(pw);
7598 pw.println();
7599 }
7600 if (startingData != null || removed || firstWindowDrawn) {
7601 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
7602 pw.print(" removed="); pw.print(removed);
7603 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
7604 }
7605 if (startingWindow != null || startingView != null
7606 || startingDisplayed || startingMoved) {
7607 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
7608 pw.print(" startingView="); pw.print(startingView);
7609 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
7610 pw.print(" startingMoved"); pw.println(startingMoved);
7611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 }
7613
7614 @Override
7615 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007616 if (stringName == null) {
7617 StringBuilder sb = new StringBuilder();
7618 sb.append("AppWindowToken{");
7619 sb.append(Integer.toHexString(System.identityHashCode(this)));
7620 sb.append(" token="); sb.append(token); sb.append('}');
7621 stringName = sb.toString();
7622 }
7623 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624 }
7625 }
Romain Guy06882f82009-06-10 13:36:04 -07007626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007627 public static WindowManager.LayoutParams findAnimations(
7628 ArrayList<AppWindowToken> order,
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07007629 ArrayList<AppWindowToken> openingTokenList1,
7630 ArrayList<AppWindowToken> closingTokenList2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 // We need to figure out which animation to use...
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07007632
7633 // First, check if there is a compatible window in opening/closing
7634 // apps, and use it if exists.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 WindowManager.LayoutParams animParams = null;
7636 int animSrc = 0;
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07007637 animParams = findCompatibleWindowParams(openingTokenList1);
7638 if (animParams == null) {
7639 animParams = findCompatibleWindowParams(closingTokenList2);
7640 }
7641 if (animParams != null) {
7642 return animParams;
7643 }
7644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 //Log.i(TAG, "Looking for animations...");
7646 for (int i=order.size()-1; i>=0; i--) {
7647 AppWindowToken wtoken = order.get(i);
7648 //Log.i(TAG, "Token " + wtoken + " with " + wtoken.windows.size() + " windows");
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07007649 if (openingTokenList1.contains(wtoken) || closingTokenList2.contains(wtoken)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 int j = wtoken.windows.size();
7651 while (j > 0) {
7652 j--;
7653 WindowState win = wtoken.windows.get(j);
7654 //Log.i(TAG, "Window " + win + ": type=" + win.mAttrs.type);
7655 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
7656 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
7657 //Log.i(TAG, "Found base or application window, done!");
7658 if (wtoken.appFullscreen) {
7659 return win.mAttrs;
7660 }
7661 if (animSrc < 2) {
7662 animParams = win.mAttrs;
7663 animSrc = 2;
7664 }
7665 } else if (animSrc < 1 && win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION) {
7666 //Log.i(TAG, "Found normal window, we may use this...");
7667 animParams = win.mAttrs;
7668 animSrc = 1;
7669 }
7670 }
7671 }
7672 }
Romain Guy06882f82009-06-10 13:36:04 -07007673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007674 return animParams;
7675 }
Romain Guy06882f82009-06-10 13:36:04 -07007676
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07007677 private static LayoutParams findCompatibleWindowParams(ArrayList<AppWindowToken> tokenList) {
7678 for (int appCount = tokenList.size() - 1; appCount >= 0; appCount--) {
7679 AppWindowToken wtoken = tokenList.get(appCount);
7680 // Just checking one window is sufficient as all windows have the compatible flag
7681 // if the application is in compatibility mode.
7682 if (wtoken.windows.size() > 0) {
7683 WindowManager.LayoutParams params = wtoken.windows.get(0).mAttrs;
7684 if ((params.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
7685 return params;
7686 }
7687 }
7688 }
7689 return null;
7690 }
7691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 // -------------------------------------------------------------
7693 // DummyAnimation
7694 // -------------------------------------------------------------
7695
7696 // This is an animation that does nothing: it just immediately finishes
7697 // itself every time it is called. It is used as a stub animation in cases
7698 // where we want to synchronize multiple things that may be animating.
7699 static final class DummyAnimation extends Animation {
7700 public boolean getTransformation(long currentTime, Transformation outTransformation) {
7701 return false;
7702 }
7703 }
7704 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07007705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 // -------------------------------------------------------------
7707 // Async Handler
7708 // -------------------------------------------------------------
7709
7710 static final class StartingData {
7711 final String pkg;
7712 final int theme;
7713 final CharSequence nonLocalizedLabel;
7714 final int labelRes;
7715 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07007716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
7718 int _labelRes, int _icon) {
7719 pkg = _pkg;
7720 theme = _theme;
7721 nonLocalizedLabel = _nonLocalizedLabel;
7722 labelRes = _labelRes;
7723 icon = _icon;
7724 }
7725 }
7726
7727 private final class H extends Handler {
7728 public static final int REPORT_FOCUS_CHANGE = 2;
7729 public static final int REPORT_LOSING_FOCUS = 3;
7730 public static final int ANIMATE = 4;
7731 public static final int ADD_STARTING = 5;
7732 public static final int REMOVE_STARTING = 6;
7733 public static final int FINISHED_STARTING = 7;
7734 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 public static final int WINDOW_FREEZE_TIMEOUT = 11;
7736 public static final int HOLD_SCREEN_CHANGED = 12;
7737 public static final int APP_TRANSITION_TIMEOUT = 13;
7738 public static final int PERSIST_ANIMATION_SCALE = 14;
7739 public static final int FORCE_GC = 15;
7740 public static final int ENABLE_SCREEN = 16;
7741 public static final int APP_FREEZE_TIMEOUT = 17;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07007742 public static final int COMPUTE_AND_SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07007743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07007745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 public H() {
7747 }
Romain Guy06882f82009-06-10 13:36:04 -07007748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 @Override
7750 public void handleMessage(Message msg) {
7751 switch (msg.what) {
7752 case REPORT_FOCUS_CHANGE: {
7753 WindowState lastFocus;
7754 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07007755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 synchronized(mWindowMap) {
7757 lastFocus = mLastFocus;
7758 newFocus = mCurrentFocus;
7759 if (lastFocus == newFocus) {
7760 // Focus is not changing, so nothing to do.
7761 return;
7762 }
7763 mLastFocus = newFocus;
7764 //Log.i(TAG, "Focus moving from " + lastFocus
7765 // + " to " + newFocus);
7766 if (newFocus != null && lastFocus != null
7767 && !newFocus.isDisplayedLw()) {
7768 //Log.i(TAG, "Delaying loss of focus...");
7769 mLosingFocus.add(lastFocus);
7770 lastFocus = null;
7771 }
7772 }
7773
7774 if (lastFocus != newFocus) {
7775 //System.out.println("Changing focus from " + lastFocus
7776 // + " to " + newFocus);
7777 if (newFocus != null) {
7778 try {
7779 //Log.i(TAG, "Gaining focus: " + newFocus);
7780 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
7781 } catch (RemoteException e) {
7782 // Ignore if process has died.
7783 }
7784 }
7785
7786 if (lastFocus != null) {
7787 try {
7788 //Log.i(TAG, "Losing focus: " + lastFocus);
7789 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
7790 } catch (RemoteException e) {
7791 // Ignore if process has died.
7792 }
7793 }
7794 }
7795 } break;
7796
7797 case REPORT_LOSING_FOCUS: {
7798 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07007799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 synchronized(mWindowMap) {
7801 losers = mLosingFocus;
7802 mLosingFocus = new ArrayList<WindowState>();
7803 }
7804
7805 final int N = losers.size();
7806 for (int i=0; i<N; i++) {
7807 try {
7808 //Log.i(TAG, "Losing delayed focus: " + losers.get(i));
7809 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
7810 } catch (RemoteException e) {
7811 // Ignore if process has died.
7812 }
7813 }
7814 } break;
7815
7816 case ANIMATE: {
7817 synchronized(mWindowMap) {
7818 mAnimationPending = false;
7819 performLayoutAndPlaceSurfacesLocked();
7820 }
7821 } break;
7822
7823 case ADD_STARTING: {
7824 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7825 final StartingData sd = wtoken.startingData;
7826
7827 if (sd == null) {
7828 // Animation has been canceled... do nothing.
7829 return;
7830 }
Romain Guy06882f82009-06-10 13:36:04 -07007831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Add starting "
7833 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07007834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 View view = null;
7836 try {
7837 view = mPolicy.addStartingWindow(
7838 wtoken.token, sd.pkg,
7839 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
7840 sd.icon);
7841 } catch (Exception e) {
7842 Log.w(TAG, "Exception when adding starting window", e);
7843 }
7844
7845 if (view != null) {
7846 boolean abort = false;
7847
7848 synchronized(mWindowMap) {
7849 if (wtoken.removed || wtoken.startingData == null) {
7850 // If the window was successfully added, then
7851 // we need to remove it.
7852 if (wtoken.startingWindow != null) {
7853 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
7854 "Aborted starting " + wtoken
7855 + ": removed=" + wtoken.removed
7856 + " startingData=" + wtoken.startingData);
7857 wtoken.startingWindow = null;
7858 wtoken.startingData = null;
7859 abort = true;
7860 }
7861 } else {
7862 wtoken.startingView = view;
7863 }
7864 if (DEBUG_STARTING_WINDOW && !abort) Log.v(TAG,
7865 "Added starting " + wtoken
7866 + ": startingWindow="
7867 + wtoken.startingWindow + " startingView="
7868 + wtoken.startingView);
7869 }
7870
7871 if (abort) {
7872 try {
7873 mPolicy.removeStartingWindow(wtoken.token, view);
7874 } catch (Exception e) {
7875 Log.w(TAG, "Exception when removing starting window", e);
7876 }
7877 }
7878 }
7879 } break;
7880
7881 case REMOVE_STARTING: {
7882 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7883 IBinder token = null;
7884 View view = null;
7885 synchronized (mWindowMap) {
7886 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Remove starting "
7887 + wtoken + ": startingWindow="
7888 + wtoken.startingWindow + " startingView="
7889 + wtoken.startingView);
7890 if (wtoken.startingWindow != null) {
7891 view = wtoken.startingView;
7892 token = wtoken.token;
7893 wtoken.startingData = null;
7894 wtoken.startingView = null;
7895 wtoken.startingWindow = null;
7896 }
7897 }
7898 if (view != null) {
7899 try {
7900 mPolicy.removeStartingWindow(token, view);
7901 } catch (Exception e) {
7902 Log.w(TAG, "Exception when removing starting window", e);
7903 }
7904 }
7905 } break;
7906
7907 case FINISHED_STARTING: {
7908 IBinder token = null;
7909 View view = null;
7910 while (true) {
7911 synchronized (mWindowMap) {
7912 final int N = mFinishedStarting.size();
7913 if (N <= 0) {
7914 break;
7915 }
7916 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7917
7918 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
7919 "Finished starting " + wtoken
7920 + ": startingWindow=" + wtoken.startingWindow
7921 + " startingView=" + wtoken.startingView);
7922
7923 if (wtoken.startingWindow == null) {
7924 continue;
7925 }
7926
7927 view = wtoken.startingView;
7928 token = wtoken.token;
7929 wtoken.startingData = null;
7930 wtoken.startingView = null;
7931 wtoken.startingWindow = null;
7932 }
7933
7934 try {
7935 mPolicy.removeStartingWindow(token, view);
7936 } catch (Exception e) {
7937 Log.w(TAG, "Exception when removing starting window", e);
7938 }
7939 }
7940 } break;
7941
7942 case REPORT_APPLICATION_TOKEN_WINDOWS: {
7943 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7944
7945 boolean nowVisible = msg.arg1 != 0;
7946 boolean nowGone = msg.arg2 != 0;
7947
7948 try {
7949 if (DEBUG_VISIBILITY) Log.v(
7950 TAG, "Reporting visible in " + wtoken
7951 + " visible=" + nowVisible
7952 + " gone=" + nowGone);
7953 if (nowVisible) {
7954 wtoken.appToken.windowsVisible();
7955 } else {
7956 wtoken.appToken.windowsGone();
7957 }
7958 } catch (RemoteException ex) {
7959 }
7960 } break;
Romain Guy06882f82009-06-10 13:36:04 -07007961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 case WINDOW_FREEZE_TIMEOUT: {
7963 synchronized (mWindowMap) {
7964 Log.w(TAG, "Window freeze timeout expired.");
7965 int i = mWindows.size();
7966 while (i > 0) {
7967 i--;
7968 WindowState w = (WindowState)mWindows.get(i);
7969 if (w.mOrientationChanging) {
7970 w.mOrientationChanging = false;
7971 Log.w(TAG, "Force clearing orientation change: " + w);
7972 }
7973 }
7974 performLayoutAndPlaceSurfacesLocked();
7975 }
7976 break;
7977 }
Romain Guy06882f82009-06-10 13:36:04 -07007978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007979 case HOLD_SCREEN_CHANGED: {
7980 Session oldHold;
7981 Session newHold;
7982 synchronized (mWindowMap) {
7983 oldHold = mLastReportedHold;
7984 newHold = (Session)msg.obj;
7985 mLastReportedHold = newHold;
7986 }
Romain Guy06882f82009-06-10 13:36:04 -07007987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007988 if (oldHold != newHold) {
7989 try {
7990 if (oldHold != null) {
7991 mBatteryStats.noteStopWakelock(oldHold.mUid,
7992 "window",
7993 BatteryStats.WAKE_TYPE_WINDOW);
7994 }
7995 if (newHold != null) {
7996 mBatteryStats.noteStartWakelock(newHold.mUid,
7997 "window",
7998 BatteryStats.WAKE_TYPE_WINDOW);
7999 }
8000 } catch (RemoteException e) {
8001 }
8002 }
8003 break;
8004 }
Romain Guy06882f82009-06-10 13:36:04 -07008005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 case APP_TRANSITION_TIMEOUT: {
8007 synchronized (mWindowMap) {
8008 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
8009 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8010 "*** APP TRANSITION TIMEOUT");
8011 mAppTransitionReady = true;
8012 mAppTransitionTimeout = true;
8013 performLayoutAndPlaceSurfacesLocked();
8014 }
8015 }
8016 break;
8017 }
Romain Guy06882f82009-06-10 13:36:04 -07008018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 case PERSIST_ANIMATION_SCALE: {
8020 Settings.System.putFloat(mContext.getContentResolver(),
8021 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
8022 Settings.System.putFloat(mContext.getContentResolver(),
8023 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
8024 break;
8025 }
Romain Guy06882f82009-06-10 13:36:04 -07008026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 case FORCE_GC: {
8028 synchronized(mWindowMap) {
8029 if (mAnimationPending) {
8030 // If we are animating, don't do the gc now but
8031 // delay a bit so we don't interrupt the animation.
8032 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
8033 2000);
8034 return;
8035 }
8036 // If we are currently rotating the display, it will
8037 // schedule a new message when done.
8038 if (mDisplayFrozen) {
8039 return;
8040 }
8041 mFreezeGcPending = 0;
8042 }
8043 Runtime.getRuntime().gc();
8044 break;
8045 }
Romain Guy06882f82009-06-10 13:36:04 -07008046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008047 case ENABLE_SCREEN: {
8048 performEnableScreen();
8049 break;
8050 }
Romain Guy06882f82009-06-10 13:36:04 -07008051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 case APP_FREEZE_TIMEOUT: {
8053 synchronized (mWindowMap) {
8054 Log.w(TAG, "App freeze timeout expired.");
8055 int i = mAppTokens.size();
8056 while (i > 0) {
8057 i--;
8058 AppWindowToken tok = mAppTokens.get(i);
8059 if (tok.freezingScreen) {
8060 Log.w(TAG, "Force clearing freeze: " + tok);
8061 unsetAppFreezingScreenLocked(tok, true, true);
8062 }
8063 }
8064 }
8065 break;
8066 }
Romain Guy06882f82009-06-10 13:36:04 -07008067
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008068 case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
Dianne Hackborncfaef692009-06-15 14:24:44 -07008069 if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008070 sendNewConfiguration();
8071 }
8072 break;
8073 }
Romain Guy06882f82009-06-10 13:36:04 -07008074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 }
8076 }
8077 }
8078
8079 // -------------------------------------------------------------
8080 // IWindowManager API
8081 // -------------------------------------------------------------
8082
8083 public IWindowSession openSession(IInputMethodClient client,
8084 IInputContext inputContext) {
8085 if (client == null) throw new IllegalArgumentException("null client");
8086 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8087 return new Session(client, inputContext);
8088 }
8089
8090 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8091 synchronized (mWindowMap) {
8092 // The focus for the client is the window immediately below
8093 // where we would place the input method window.
8094 int idx = findDesiredInputMethodWindowIndexLocked(false);
8095 WindowState imFocus;
8096 if (idx > 0) {
8097 imFocus = (WindowState)mWindows.get(idx-1);
8098 if (imFocus != null) {
8099 if (imFocus.mSession.mClient != null &&
8100 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8101 return true;
8102 }
8103 }
8104 }
8105 }
8106 return false;
8107 }
Romain Guy06882f82009-06-10 13:36:04 -07008108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 // -------------------------------------------------------------
8110 // Internals
8111 // -------------------------------------------------------------
8112
8113 final WindowState windowForClientLocked(Session session, IWindow client) {
8114 return windowForClientLocked(session, client.asBinder());
8115 }
Romain Guy06882f82009-06-10 13:36:04 -07008116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 final WindowState windowForClientLocked(Session session, IBinder client) {
8118 WindowState win = mWindowMap.get(client);
8119 if (localLOGV) Log.v(
8120 TAG, "Looking up client " + client + ": " + win);
8121 if (win == null) {
8122 RuntimeException ex = new RuntimeException();
8123 Log.w(TAG, "Requested window " + client + " does not exist", ex);
8124 return null;
8125 }
8126 if (session != null && win.mSession != session) {
8127 RuntimeException ex = new RuntimeException();
8128 Log.w(TAG, "Requested window " + client + " is in session " +
8129 win.mSession + ", not " + session, ex);
8130 return null;
8131 }
8132
8133 return win;
8134 }
8135
8136 private final void assignLayersLocked() {
8137 int N = mWindows.size();
8138 int curBaseLayer = 0;
8139 int curLayer = 0;
8140 int i;
Romain Guy06882f82009-06-10 13:36:04 -07008141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 for (i=0; i<N; i++) {
8143 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008144 if (w.mBaseLayer == curBaseLayer || w.mIsFloatingLayer) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 curLayer += WINDOW_LAYER_MULTIPLIER;
8146 w.mLayer = curLayer;
8147 } else {
8148 curBaseLayer = curLayer = w.mBaseLayer;
8149 w.mLayer = curLayer;
8150 }
8151 if (w.mTargetAppToken != null) {
8152 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
8153 } else if (w.mAppToken != null) {
8154 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
8155 } else {
8156 w.mAnimLayer = w.mLayer;
8157 }
8158 if (w.mIsImWindow) {
8159 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008160 } else if (w.mIsWallpaper) {
8161 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 }
8163 if (DEBUG_LAYERS) Log.v(TAG, "Assign layer " + w + ": "
8164 + w.mAnimLayer);
8165 //System.out.println(
8166 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8167 }
8168 }
8169
8170 private boolean mInLayout = false;
8171 private final void performLayoutAndPlaceSurfacesLocked() {
8172 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -07008173 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 throw new RuntimeException("Recursive call!");
8175 }
8176 Log.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
8177 return;
8178 }
8179
8180 boolean recoveringMemory = false;
8181 if (mForceRemoves != null) {
8182 recoveringMemory = true;
8183 // Wait a little it for things to settle down, and off we go.
8184 for (int i=0; i<mForceRemoves.size(); i++) {
8185 WindowState ws = mForceRemoves.get(i);
8186 Log.i(TAG, "Force removing: " + ws);
8187 removeWindowInnerLocked(ws.mSession, ws);
8188 }
8189 mForceRemoves = null;
8190 Log.w(TAG, "Due to memory failure, waiting a bit for next layout");
8191 Object tmp = new Object();
8192 synchronized (tmp) {
8193 try {
8194 tmp.wait(250);
8195 } catch (InterruptedException e) {
8196 }
8197 }
8198 }
Romain Guy06882f82009-06-10 13:36:04 -07008199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 mInLayout = true;
8201 try {
8202 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -07008203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 int i = mPendingRemove.size()-1;
8205 if (i >= 0) {
8206 while (i >= 0) {
8207 WindowState w = mPendingRemove.get(i);
8208 removeWindowInnerLocked(w.mSession, w);
8209 i--;
8210 }
8211 mPendingRemove.clear();
8212
8213 mInLayout = false;
8214 assignLayersLocked();
8215 mLayoutNeeded = true;
8216 performLayoutAndPlaceSurfacesLocked();
8217
8218 } else {
8219 mInLayout = false;
8220 if (mLayoutNeeded) {
8221 requestAnimationLocked(0);
8222 }
8223 }
8224 } catch (RuntimeException e) {
8225 mInLayout = false;
8226 Log.e(TAG, "Unhandled exception while layout out windows", e);
8227 }
8228 }
8229
8230 private final void performLayoutLockedInner() {
8231 final int dw = mDisplay.getWidth();
8232 final int dh = mDisplay.getHeight();
8233
8234 final int N = mWindows.size();
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008235 int repeats = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 int i;
8237
8238 // FIRST LOOP: Perform a layout, if needed.
Romain Guy06882f82009-06-10 13:36:04 -07008239
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008240 while (mLayoutNeeded) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008241 mPolicy.beginLayoutLw(dw, dh);
8242
8243 // First perform layout of any root windows (not attached
8244 // to another window).
8245 int topAttached = -1;
8246 for (i = N-1; i >= 0; i--) {
8247 WindowState win = (WindowState) mWindows.get(i);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008248
8249 // Don't do layout of a window if it is not visible, or
8250 // soon won't be visible, to avoid wasting time and funky
8251 // changes while a window is animating away.
8252 final AppWindowToken atoken = win.mAppToken;
8253 final boolean gone = win.mViewVisibility == View.GONE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 || !win.mRelayoutCalled
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008255 || win.mRootToken.hidden
8256 || (atoken != null && atoken.hiddenRequested)
8257 || !win.mPolicyVisibility
8258 || win.mAttachedHidden
8259 || win.mExiting || win.mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260
8261 // If this view is GONE, then skip it -- keep the current
8262 // frame, and let the caller know so they can ignore it
8263 // if they want. (We do the normal layout for INVISIBLE
8264 // windows, since that means "perform layout as normal,
8265 // just don't display").
8266 if (!gone || !win.mHaveFrame) {
8267 if (!win.mLayoutAttached) {
8268 mPolicy.layoutWindowLw(win, win.mAttrs, null);
8269 } else {
8270 if (topAttached < 0) topAttached = i;
8271 }
8272 }
8273 }
Romain Guy06882f82009-06-10 13:36:04 -07008274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 // Now perform layout of attached windows, which usually
8276 // depend on the position of the window they are attached to.
8277 // XXX does not deal with windows that are attached to windows
8278 // that are themselves attached.
8279 for (i = topAttached; i >= 0; i--) {
8280 WindowState win = (WindowState) mWindows.get(i);
8281
8282 // If this view is GONE, then skip it -- keep the current
8283 // frame, and let the caller know so they can ignore it
8284 // if they want. (We do the normal layout for INVISIBLE
8285 // windows, since that means "perform layout as normal,
8286 // just don't display").
8287 if (win.mLayoutAttached) {
8288 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8289 || !win.mHaveFrame) {
8290 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8291 }
8292 }
8293 }
8294
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008295 if (!mPolicy.finishLayoutLw()) {
8296 mLayoutNeeded = false;
8297 } else if (repeats > 2) {
8298 Log.w(TAG, "Layout repeat aborted after too many iterations");
8299 mLayoutNeeded = false;
8300 } else {
8301 repeats++;
8302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 }
8304 }
Romain Guy06882f82009-06-10 13:36:04 -07008305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008306 private final void performLayoutAndPlaceSurfacesLockedInner(
8307 boolean recoveringMemory) {
8308 final long currentTime = SystemClock.uptimeMillis();
8309 final int dw = mDisplay.getWidth();
8310 final int dh = mDisplay.getHeight();
8311
8312 final int N = mWindows.size();
8313 int i;
8314
8315 // FIRST LOOP: Perform a layout, if needed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 performLayoutLockedInner();
Romain Guy06882f82009-06-10 13:36:04 -07008317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 if (mFxSession == null) {
8319 mFxSession = new SurfaceSession();
8320 }
Romain Guy06882f82009-06-10 13:36:04 -07008321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
8323
8324 // Initialize state of exiting tokens.
8325 for (i=mExitingTokens.size()-1; i>=0; i--) {
8326 mExitingTokens.get(i).hasVisible = false;
8327 }
8328
8329 // Initialize state of exiting applications.
8330 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
8331 mExitingAppTokens.get(i).hasVisible = false;
8332 }
8333
8334 // SECOND LOOP: Execute animations and update visibility of windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 boolean orientationChangeComplete = true;
8336 Session holdScreen = null;
8337 float screenBrightness = -1;
8338 boolean focusDisplayed = false;
8339 boolean animating = false;
8340
8341 Surface.openTransaction();
8342 try {
8343 boolean restart;
8344
8345 do {
8346 final int transactionSequence = ++mTransactionSequence;
8347
8348 // Update animations of all applications, including those
8349 // associated with exiting/removed apps
8350 boolean tokensAnimating = false;
8351 final int NAT = mAppTokens.size();
8352 for (i=0; i<NAT; i++) {
8353 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
8354 tokensAnimating = true;
8355 }
8356 }
8357 final int NEAT = mExitingAppTokens.size();
8358 for (i=0; i<NEAT; i++) {
8359 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
8360 tokensAnimating = true;
8361 }
8362 }
8363
8364 animating = tokensAnimating;
8365 restart = false;
8366
8367 boolean tokenMayBeDrawn = false;
8368
8369 mPolicy.beginAnimationLw(dw, dh);
8370
8371 for (i=N-1; i>=0; i--) {
8372 WindowState w = (WindowState)mWindows.get(i);
8373
8374 final WindowManager.LayoutParams attrs = w.mAttrs;
8375
8376 if (w.mSurface != null) {
8377 // Execute animation.
8378 w.commitFinishDrawingLocked(currentTime);
8379 if (w.stepAnimationLocked(currentTime, dw, dh)) {
8380 animating = true;
8381 //w.dump(" ");
8382 }
8383
8384 mPolicy.animatingWindowLw(w, attrs);
8385 }
8386
8387 final AppWindowToken atoken = w.mAppToken;
8388 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
8389 if (atoken.lastTransactionSequence != transactionSequence) {
8390 atoken.lastTransactionSequence = transactionSequence;
8391 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
8392 atoken.startingDisplayed = false;
8393 }
8394 if ((w.isOnScreen() || w.mAttrs.type
8395 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
8396 && !w.mExiting && !w.mDestroying) {
8397 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
8398 Log.v(TAG, "Eval win " + w + ": isDisplayed="
8399 + w.isDisplayedLw()
8400 + ", isAnimating=" + w.isAnimating());
8401 if (!w.isDisplayedLw()) {
8402 Log.v(TAG, "Not displayed: s=" + w.mSurface
8403 + " pv=" + w.mPolicyVisibility
8404 + " dp=" + w.mDrawPending
8405 + " cdp=" + w.mCommitDrawPending
8406 + " ah=" + w.mAttachedHidden
8407 + " th=" + atoken.hiddenRequested
8408 + " a=" + w.mAnimating);
8409 }
8410 }
8411 if (w != atoken.startingWindow) {
8412 if (!atoken.freezingScreen || !w.mAppFreezing) {
8413 atoken.numInterestingWindows++;
8414 if (w.isDisplayedLw()) {
8415 atoken.numDrawnWindows++;
8416 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Log.v(TAG,
8417 "tokenMayBeDrawn: " + atoken
8418 + " freezingScreen=" + atoken.freezingScreen
8419 + " mAppFreezing=" + w.mAppFreezing);
8420 tokenMayBeDrawn = true;
8421 }
8422 }
8423 } else if (w.isDisplayedLw()) {
8424 atoken.startingDisplayed = true;
8425 }
8426 }
8427 } else if (w.mReadyToShow) {
8428 w.performShowLocked();
8429 }
8430 }
8431
8432 if (mPolicy.finishAnimationLw()) {
8433 restart = true;
8434 }
8435
8436 if (tokenMayBeDrawn) {
8437 // See if any windows have been drawn, so they (and others
8438 // associated with them) can now be shown.
8439 final int NT = mTokenList.size();
8440 for (i=0; i<NT; i++) {
8441 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
8442 if (wtoken == null) {
8443 continue;
8444 }
8445 if (wtoken.freezingScreen) {
8446 int numInteresting = wtoken.numInterestingWindows;
8447 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8448 if (DEBUG_VISIBILITY) Log.v(TAG,
8449 "allDrawn: " + wtoken
8450 + " interesting=" + numInteresting
8451 + " drawn=" + wtoken.numDrawnWindows);
8452 wtoken.showAllWindowsLocked();
8453 unsetAppFreezingScreenLocked(wtoken, false, true);
8454 orientationChangeComplete = true;
8455 }
8456 } else if (!wtoken.allDrawn) {
8457 int numInteresting = wtoken.numInterestingWindows;
8458 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8459 if (DEBUG_VISIBILITY) Log.v(TAG,
8460 "allDrawn: " + wtoken
8461 + " interesting=" + numInteresting
8462 + " drawn=" + wtoken.numDrawnWindows);
8463 wtoken.allDrawn = true;
8464 restart = true;
8465
8466 // We can now show all of the drawn windows!
8467 if (!mOpeningApps.contains(wtoken)) {
8468 wtoken.showAllWindowsLocked();
8469 }
8470 }
8471 }
8472 }
8473 }
8474
8475 // If we are ready to perform an app transition, check through
8476 // all of the app tokens to be shown and see if they are ready
8477 // to go.
8478 if (mAppTransitionReady) {
8479 int NN = mOpeningApps.size();
8480 boolean goodToGo = true;
8481 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8482 "Checking " + NN + " opening apps (frozen="
8483 + mDisplayFrozen + " timeout="
8484 + mAppTransitionTimeout + ")...");
8485 if (!mDisplayFrozen && !mAppTransitionTimeout) {
8486 // If the display isn't frozen, wait to do anything until
8487 // all of the apps are ready. Otherwise just go because
8488 // we'll unfreeze the display when everyone is ready.
8489 for (i=0; i<NN && goodToGo; i++) {
8490 AppWindowToken wtoken = mOpeningApps.get(i);
8491 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8492 "Check opening app" + wtoken + ": allDrawn="
8493 + wtoken.allDrawn + " startingDisplayed="
8494 + wtoken.startingDisplayed);
8495 if (!wtoken.allDrawn && !wtoken.startingDisplayed
8496 && !wtoken.startingMoved) {
8497 goodToGo = false;
8498 }
8499 }
8500 }
8501 if (goodToGo) {
8502 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "**** GOOD TO GO");
8503 int transit = mNextAppTransition;
8504 if (mSkipAppTransitionAnimation) {
8505 transit = WindowManagerPolicy.TRANSIT_NONE;
8506 }
8507 mNextAppTransition = WindowManagerPolicy.TRANSIT_NONE;
8508 mAppTransitionReady = false;
8509 mAppTransitionTimeout = false;
8510 mStartingIconInTransition = false;
8511 mSkipAppTransitionAnimation = false;
8512
8513 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8514
8515 // We need to figure out which animation to use...
8516 WindowManager.LayoutParams lp = findAnimations(mAppTokens,
8517 mOpeningApps, mClosingApps);
8518
8519 NN = mOpeningApps.size();
8520 for (i=0; i<NN; i++) {
8521 AppWindowToken wtoken = mOpeningApps.get(i);
8522 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8523 "Now opening app" + wtoken);
8524 wtoken.reportedVisible = false;
8525 wtoken.inPendingTransaction = false;
8526 setTokenVisibilityLocked(wtoken, lp, true, transit, false);
8527 wtoken.updateReportedVisibilityLocked();
8528 wtoken.showAllWindowsLocked();
8529 }
8530 NN = mClosingApps.size();
8531 for (i=0; i<NN; i++) {
8532 AppWindowToken wtoken = mClosingApps.get(i);
8533 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8534 "Now closing app" + wtoken);
8535 wtoken.inPendingTransaction = false;
8536 setTokenVisibilityLocked(wtoken, lp, false, transit, false);
8537 wtoken.updateReportedVisibilityLocked();
8538 // Force the allDrawn flag, because we want to start
8539 // this guy's animations regardless of whether it's
8540 // gotten drawn.
8541 wtoken.allDrawn = true;
8542 }
8543
8544 mOpeningApps.clear();
8545 mClosingApps.clear();
8546
8547 // This has changed the visibility of windows, so perform
8548 // a new layout to get them all up-to-date.
8549 mLayoutNeeded = true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008550 adjustWallpaperWindowsLocked();
Dianne Hackborn20583ff2009-07-27 21:51:05 -07008551 if (!moveInputMethodWindowsIfNeededLocked(true)) {
8552 assignLayersLocked();
8553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 performLayoutLockedInner();
8555 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
8556
8557 restart = true;
8558 }
8559 }
8560 } while (restart);
8561
8562 // THIRD LOOP: Update the surfaces of all windows.
8563
8564 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
8565
8566 boolean obscured = false;
8567 boolean blurring = false;
8568 boolean dimming = false;
8569 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07008570 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008571 boolean backgroundFillerShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572
8573 for (i=N-1; i>=0; i--) {
8574 WindowState w = (WindowState)mWindows.get(i);
8575
8576 boolean displayed = false;
8577 final WindowManager.LayoutParams attrs = w.mAttrs;
8578 final int attrFlags = attrs.flags;
8579
8580 if (w.mSurface != null) {
8581 w.computeShownFrameLocked();
8582 if (localLOGV) Log.v(
8583 TAG, "Placing surface #" + i + " " + w.mSurface
8584 + ": new=" + w.mShownFrame + ", old="
8585 + w.mLastShownFrame);
8586
8587 boolean resize;
8588 int width, height;
8589 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
8590 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
8591 w.mLastRequestedHeight != w.mRequestedHeight;
8592 // for a scaled surface, we just want to use
8593 // the requested size.
8594 width = w.mRequestedWidth;
8595 height = w.mRequestedHeight;
8596 w.mLastRequestedWidth = width;
8597 w.mLastRequestedHeight = height;
8598 w.mLastShownFrame.set(w.mShownFrame);
8599 try {
8600 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
8601 } catch (RuntimeException e) {
8602 Log.w(TAG, "Error positioning surface in " + w, e);
8603 if (!recoveringMemory) {
8604 reclaimSomeSurfaceMemoryLocked(w, "position");
8605 }
8606 }
8607 } else {
8608 resize = !w.mLastShownFrame.equals(w.mShownFrame);
8609 width = w.mShownFrame.width();
8610 height = w.mShownFrame.height();
8611 w.mLastShownFrame.set(w.mShownFrame);
8612 if (resize) {
8613 if (SHOW_TRANSACTIONS) Log.i(
8614 TAG, " SURFACE " + w.mSurface + ": ("
8615 + w.mShownFrame.left + ","
8616 + w.mShownFrame.top + ") ("
8617 + w.mShownFrame.width() + "x"
8618 + w.mShownFrame.height() + ")");
8619 }
8620 }
8621
8622 if (resize) {
8623 if (width < 1) width = 1;
8624 if (height < 1) height = 1;
8625 if (w.mSurface != null) {
8626 try {
8627 w.mSurface.setSize(width, height);
8628 w.mSurface.setPosition(w.mShownFrame.left,
8629 w.mShownFrame.top);
8630 } catch (RuntimeException e) {
8631 // If something goes wrong with the surface (such
8632 // as running out of memory), don't take down the
8633 // entire system.
8634 Log.e(TAG, "Failure updating surface of " + w
8635 + "size=(" + width + "x" + height
8636 + "), pos=(" + w.mShownFrame.left
8637 + "," + w.mShownFrame.top + ")", e);
8638 if (!recoveringMemory) {
8639 reclaimSomeSurfaceMemoryLocked(w, "size");
8640 }
8641 }
8642 }
8643 }
8644 if (!w.mAppFreezing) {
8645 w.mContentInsetsChanged =
8646 !w.mLastContentInsets.equals(w.mContentInsets);
8647 w.mVisibleInsetsChanged =
8648 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Romain Guy06882f82009-06-10 13:36:04 -07008649 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 || w.mContentInsetsChanged
8651 || w.mVisibleInsetsChanged) {
8652 w.mLastFrame.set(w.mFrame);
8653 w.mLastContentInsets.set(w.mContentInsets);
8654 w.mLastVisibleInsets.set(w.mVisibleInsets);
8655 // If the orientation is changing, then we need to
8656 // hold off on unfreezing the display until this
8657 // window has been redrawn; to do that, we need
8658 // to go through the process of getting informed
8659 // by the application when it has finished drawing.
8660 if (w.mOrientationChanging) {
8661 if (DEBUG_ORIENTATION) Log.v(TAG,
8662 "Orientation start waiting for draw in "
8663 + w + ", surface " + w.mSurface);
8664 w.mDrawPending = true;
8665 w.mCommitDrawPending = false;
8666 w.mReadyToShow = false;
8667 if (w.mAppToken != null) {
8668 w.mAppToken.allDrawn = false;
8669 }
8670 }
Romain Guy06882f82009-06-10 13:36:04 -07008671 if (DEBUG_ORIENTATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 "Resizing window " + w + " to " + w.mFrame);
8673 mResizingWindows.add(w);
8674 } else if (w.mOrientationChanging) {
8675 if (!w.mDrawPending && !w.mCommitDrawPending) {
8676 if (DEBUG_ORIENTATION) Log.v(TAG,
8677 "Orientation not waiting for draw in "
8678 + w + ", surface " + w.mSurface);
8679 w.mOrientationChanging = false;
8680 }
8681 }
8682 }
8683
8684 if (w.mAttachedHidden) {
8685 if (!w.mLastHidden) {
8686 //dump();
8687 w.mLastHidden = true;
8688 if (SHOW_TRANSACTIONS) Log.i(
8689 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout-attached)");
8690 if (w.mSurface != null) {
8691 try {
8692 w.mSurface.hide();
8693 } catch (RuntimeException e) {
8694 Log.w(TAG, "Exception hiding surface in " + w);
8695 }
8696 }
8697 mKeyWaiter.releasePendingPointerLocked(w.mSession);
8698 }
8699 // If we are waiting for this window to handle an
8700 // orientation change, well, it is hidden, so
8701 // doesn't really matter. Note that this does
8702 // introduce a potential glitch if the window
8703 // becomes unhidden before it has drawn for the
8704 // new orientation.
8705 if (w.mOrientationChanging) {
8706 w.mOrientationChanging = false;
8707 if (DEBUG_ORIENTATION) Log.v(TAG,
8708 "Orientation change skips hidden " + w);
8709 }
8710 } else if (!w.isReadyForDisplay()) {
8711 if (!w.mLastHidden) {
8712 //dump();
8713 w.mLastHidden = true;
8714 if (SHOW_TRANSACTIONS) Log.i(
8715 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout-ready)");
8716 if (w.mSurface != null) {
8717 try {
8718 w.mSurface.hide();
8719 } catch (RuntimeException e) {
8720 Log.w(TAG, "Exception exception hiding surface in " + w);
8721 }
8722 }
8723 mKeyWaiter.releasePendingPointerLocked(w.mSession);
8724 }
8725 // If we are waiting for this window to handle an
8726 // orientation change, well, it is hidden, so
8727 // doesn't really matter. Note that this does
8728 // introduce a potential glitch if the window
8729 // becomes unhidden before it has drawn for the
8730 // new orientation.
8731 if (w.mOrientationChanging) {
8732 w.mOrientationChanging = false;
8733 if (DEBUG_ORIENTATION) Log.v(TAG,
8734 "Orientation change skips hidden " + w);
8735 }
8736 } else if (w.mLastLayer != w.mAnimLayer
8737 || w.mLastAlpha != w.mShownAlpha
8738 || w.mLastDsDx != w.mDsDx
8739 || w.mLastDtDx != w.mDtDx
8740 || w.mLastDsDy != w.mDsDy
8741 || w.mLastDtDy != w.mDtDy
8742 || w.mLastHScale != w.mHScale
8743 || w.mLastVScale != w.mVScale
8744 || w.mLastHidden) {
8745 displayed = true;
8746 w.mLastAlpha = w.mShownAlpha;
8747 w.mLastLayer = w.mAnimLayer;
8748 w.mLastDsDx = w.mDsDx;
8749 w.mLastDtDx = w.mDtDx;
8750 w.mLastDsDy = w.mDsDy;
8751 w.mLastDtDy = w.mDtDy;
8752 w.mLastHScale = w.mHScale;
8753 w.mLastVScale = w.mVScale;
8754 if (SHOW_TRANSACTIONS) Log.i(
8755 TAG, " SURFACE " + w.mSurface + ": alpha="
8756 + w.mShownAlpha + " layer=" + w.mAnimLayer);
8757 if (w.mSurface != null) {
8758 try {
8759 w.mSurface.setAlpha(w.mShownAlpha);
8760 w.mSurface.setLayer(w.mAnimLayer);
8761 w.mSurface.setMatrix(
8762 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
8763 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
8764 } catch (RuntimeException e) {
8765 Log.w(TAG, "Error updating surface in " + w, e);
8766 if (!recoveringMemory) {
8767 reclaimSomeSurfaceMemoryLocked(w, "update");
8768 }
8769 }
8770 }
8771
8772 if (w.mLastHidden && !w.mDrawPending
8773 && !w.mCommitDrawPending
8774 && !w.mReadyToShow) {
8775 if (SHOW_TRANSACTIONS) Log.i(
8776 TAG, " SURFACE " + w.mSurface + ": SHOW (performLayout)");
8777 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + w
8778 + " during relayout");
8779 if (showSurfaceRobustlyLocked(w)) {
8780 w.mHasDrawn = true;
8781 w.mLastHidden = false;
8782 } else {
8783 w.mOrientationChanging = false;
8784 }
8785 }
8786 if (w.mSurface != null) {
8787 w.mToken.hasVisible = true;
8788 }
8789 } else {
8790 displayed = true;
8791 }
8792
8793 if (displayed) {
8794 if (!covered) {
8795 if (attrs.width == LayoutParams.FILL_PARENT
8796 && attrs.height == LayoutParams.FILL_PARENT) {
8797 covered = true;
8798 }
8799 }
8800 if (w.mOrientationChanging) {
8801 if (w.mDrawPending || w.mCommitDrawPending) {
8802 orientationChangeComplete = false;
8803 if (DEBUG_ORIENTATION) Log.v(TAG,
8804 "Orientation continue waiting for draw in " + w);
8805 } else {
8806 w.mOrientationChanging = false;
8807 if (DEBUG_ORIENTATION) Log.v(TAG,
8808 "Orientation change complete in " + w);
8809 }
8810 }
8811 w.mToken.hasVisible = true;
8812 }
8813 } else if (w.mOrientationChanging) {
8814 if (DEBUG_ORIENTATION) Log.v(TAG,
8815 "Orientation change skips hidden " + w);
8816 w.mOrientationChanging = false;
8817 }
8818
8819 final boolean canBeSeen = w.isDisplayedLw();
8820
8821 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
8822 focusDisplayed = true;
8823 }
8824
8825 // Update effect.
8826 if (!obscured) {
8827 if (w.mSurface != null) {
8828 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8829 holdScreen = w.mSession;
8830 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07008831 if (!syswin && w.mAttrs.screenBrightness >= 0
8832 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833 screenBrightness = w.mAttrs.screenBrightness;
8834 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07008835 if (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
8836 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
8837 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR) {
8838 syswin = true;
8839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008841
8842 boolean opaqueDrawn = w.isOpaqueDrawn();
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008843 if ((opaqueDrawn && w.isFullscreen(dw, dh))
8844 || attrs.type == TYPE_WALLPAPER) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 // This window completely covers everything behind it,
8846 // so we want to leave all of them as unblurred (for
8847 // performance reasons).
8848 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008849 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
8850 if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008851 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008852 obscured = true;
8853 if (mBackgroundFillerSurface == null) {
8854 try {
8855 mBackgroundFillerSurface = new Surface(mFxSession, 0,
8856 0, dw, dh,
8857 PixelFormat.OPAQUE,
8858 Surface.FX_SURFACE_NORMAL);
8859 } catch (Exception e) {
8860 Log.e(TAG, "Exception creating filler surface", e);
8861 }
8862 }
8863 try {
8864 mBackgroundFillerSurface.setPosition(0, 0);
8865 mBackgroundFillerSurface.setSize(dw, dh);
8866 // Using the same layer as Dim because they will never be shown at the
8867 // same time.
8868 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
8869 mBackgroundFillerSurface.show();
8870 } catch (RuntimeException e) {
8871 Log.e(TAG, "Exception showing filler surface");
8872 }
8873 backgroundFillerShown = true;
8874 mBackgroundFillerShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008875 } else if (canBeSeen && !obscured &&
8876 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
8877 if (localLOGV) Log.v(TAG, "Win " + w
8878 + ": blurring=" + blurring
8879 + " obscured=" + obscured
8880 + " displayed=" + displayed);
8881 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
8882 if (!dimming) {
8883 //Log.i(TAG, "DIM BEHIND: " + w);
8884 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008885 if (mDimAnimator == null) {
8886 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008888 mDimAnimator.show(dw, dh);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008889 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008890 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008891 }
8892 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
8893 if (!blurring) {
8894 //Log.i(TAG, "BLUR BEHIND: " + w);
8895 blurring = true;
8896 mBlurShown = true;
8897 if (mBlurSurface == null) {
8898 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
8899 + mBlurSurface + ": CREATE");
8900 try {
Romain Guy06882f82009-06-10 13:36:04 -07008901 mBlurSurface = new Surface(mFxSession, 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008902 -1, 16, 16,
8903 PixelFormat.OPAQUE,
8904 Surface.FX_SURFACE_BLUR);
8905 } catch (Exception e) {
8906 Log.e(TAG, "Exception creating Blur surface", e);
8907 }
8908 }
8909 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
8910 + mBlurSurface + ": SHOW pos=(0,0) (" +
8911 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
8912 if (mBlurSurface != null) {
8913 mBlurSurface.setPosition(0, 0);
8914 mBlurSurface.setSize(dw, dh);
8915 try {
8916 mBlurSurface.show();
8917 } catch (RuntimeException e) {
8918 Log.w(TAG, "Failure showing blur surface", e);
8919 }
8920 }
8921 }
8922 mBlurSurface.setLayer(w.mAnimLayer-2);
8923 }
8924 }
8925 }
8926 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008927
8928 if (backgroundFillerShown == false && mBackgroundFillerShown) {
8929 mBackgroundFillerShown = false;
8930 if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler");
8931 try {
8932 mBackgroundFillerSurface.hide();
8933 } catch (RuntimeException e) {
8934 Log.e(TAG, "Exception hiding filler surface", e);
8935 }
8936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008938 if (mDimAnimator != null && mDimAnimator.mDimShown) {
8939 animating |= mDimAnimator.updateSurface(dimming, currentTime, mDisplayFrozen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008940 }
Romain Guy06882f82009-06-10 13:36:04 -07008941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 if (!blurring && mBlurShown) {
8943 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR " + mBlurSurface
8944 + ": HIDE");
8945 try {
8946 mBlurSurface.hide();
8947 } catch (IllegalArgumentException e) {
8948 Log.w(TAG, "Illegal argument exception hiding blur surface");
8949 }
8950 mBlurShown = false;
8951 }
8952
8953 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
8954 } catch (RuntimeException e) {
8955 Log.e(TAG, "Unhandled exception in Window Manager", e);
8956 }
8957
8958 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -07008959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960 if (DEBUG_ORIENTATION && mDisplayFrozen) Log.v(TAG,
8961 "With display frozen, orientationChangeComplete="
8962 + orientationChangeComplete);
8963 if (orientationChangeComplete) {
8964 if (mWindowsFreezingScreen) {
8965 mWindowsFreezingScreen = false;
8966 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8967 }
8968 if (mAppsFreezingScreen == 0) {
8969 stopFreezingDisplayLocked();
8970 }
8971 }
Romain Guy06882f82009-06-10 13:36:04 -07008972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 i = mResizingWindows.size();
8974 if (i > 0) {
8975 do {
8976 i--;
8977 WindowState win = mResizingWindows.get(i);
8978 try {
8979 win.mClient.resized(win.mFrame.width(),
8980 win.mFrame.height(), win.mLastContentInsets,
8981 win.mLastVisibleInsets, win.mDrawPending);
8982 win.mContentInsetsChanged = false;
8983 win.mVisibleInsetsChanged = false;
8984 } catch (RemoteException e) {
8985 win.mOrientationChanging = false;
8986 }
8987 } while (i > 0);
8988 mResizingWindows.clear();
8989 }
Romain Guy06882f82009-06-10 13:36:04 -07008990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 // Destroy the surface of any windows that are no longer visible.
8992 i = mDestroySurface.size();
8993 if (i > 0) {
8994 do {
8995 i--;
8996 WindowState win = mDestroySurface.get(i);
8997 win.mDestroying = false;
8998 if (mInputMethodWindow == win) {
8999 mInputMethodWindow = null;
9000 }
9001 win.destroySurfaceLocked();
9002 } while (i > 0);
9003 mDestroySurface.clear();
9004 }
9005
9006 // Time to remove any exiting tokens?
9007 for (i=mExitingTokens.size()-1; i>=0; i--) {
9008 WindowToken token = mExitingTokens.get(i);
9009 if (!token.hasVisible) {
9010 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07009011 if (token.windowType == TYPE_WALLPAPER) {
9012 mWallpaperTokens.remove(token);
9013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009014 }
9015 }
9016
9017 // Time to remove any exiting applications?
9018 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9019 AppWindowToken token = mExitingAppTokens.get(i);
9020 if (!token.hasVisible && !mClosingApps.contains(token)) {
9021 mAppTokens.remove(token);
9022 mExitingAppTokens.remove(i);
9023 }
9024 }
9025
9026 if (focusDisplayed) {
9027 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9028 }
9029 if (animating) {
9030 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
9031 }
9032 mQueue.setHoldScreenLocked(holdScreen != null);
9033 if (screenBrightness < 0 || screenBrightness > 1.0f) {
9034 mPowerManager.setScreenBrightnessOverride(-1);
9035 } else {
9036 mPowerManager.setScreenBrightnessOverride((int)
9037 (screenBrightness * Power.BRIGHTNESS_ON));
9038 }
9039 if (holdScreen != mHoldingScreenOn) {
9040 mHoldingScreenOn = holdScreen;
9041 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
9042 mH.sendMessage(m);
9043 }
9044 }
9045
9046 void requestAnimationLocked(long delay) {
9047 if (!mAnimationPending) {
9048 mAnimationPending = true;
9049 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
9050 }
9051 }
Romain Guy06882f82009-06-10 13:36:04 -07009052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 /**
9054 * Have the surface flinger show a surface, robustly dealing with
9055 * error conditions. In particular, if there is not enough memory
9056 * to show the surface, then we will try to get rid of other surfaces
9057 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -07009058 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 * @return Returns true if the surface was successfully shown.
9060 */
9061 boolean showSurfaceRobustlyLocked(WindowState win) {
9062 try {
9063 if (win.mSurface != null) {
9064 win.mSurface.show();
9065 }
9066 return true;
9067 } catch (RuntimeException e) {
9068 Log.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
9069 }
Romain Guy06882f82009-06-10 13:36:04 -07009070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -07009072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 return false;
9074 }
Romain Guy06882f82009-06-10 13:36:04 -07009075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009076 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
9077 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -07009078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009079 EventLog.writeEvent(LOG_WM_NO_SURFACE_MEMORY, win.toString(),
9080 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -07009081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 if (mForceRemoves == null) {
9083 mForceRemoves = new ArrayList<WindowState>();
9084 }
Romain Guy06882f82009-06-10 13:36:04 -07009085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 long callingIdentity = Binder.clearCallingIdentity();
9087 try {
9088 // There was some problem... first, do a sanity check of the
9089 // window list to make sure we haven't left any dangling surfaces
9090 // around.
9091 int N = mWindows.size();
9092 boolean leakedSurface = false;
9093 Log.i(TAG, "Out of memory for surface! Looking for leaks...");
9094 for (int i=0; i<N; i++) {
9095 WindowState ws = (WindowState)mWindows.get(i);
9096 if (ws.mSurface != null) {
9097 if (!mSessions.contains(ws.mSession)) {
9098 Log.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9099 + ws + " surface=" + ws.mSurface
9100 + " token=" + win.mToken
9101 + " pid=" + ws.mSession.mPid
9102 + " uid=" + ws.mSession.mUid);
9103 ws.mSurface.clear();
9104 ws.mSurface = null;
9105 mForceRemoves.add(ws);
9106 i--;
9107 N--;
9108 leakedSurface = true;
9109 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
9110 Log.w(TAG, "LEAKED SURFACE (app token hidden): "
9111 + ws + " surface=" + ws.mSurface
9112 + " token=" + win.mAppToken);
9113 ws.mSurface.clear();
9114 ws.mSurface = null;
9115 leakedSurface = true;
9116 }
9117 }
9118 }
Romain Guy06882f82009-06-10 13:36:04 -07009119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 boolean killedApps = false;
9121 if (!leakedSurface) {
9122 Log.w(TAG, "No leaked surfaces; killing applicatons!");
9123 SparseIntArray pidCandidates = new SparseIntArray();
9124 for (int i=0; i<N; i++) {
9125 WindowState ws = (WindowState)mWindows.get(i);
9126 if (ws.mSurface != null) {
9127 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
9128 }
9129 }
9130 if (pidCandidates.size() > 0) {
9131 int[] pids = new int[pidCandidates.size()];
9132 for (int i=0; i<pids.length; i++) {
9133 pids[i] = pidCandidates.keyAt(i);
9134 }
9135 try {
9136 if (mActivityManager.killPidsForMemory(pids)) {
9137 killedApps = true;
9138 }
9139 } catch (RemoteException e) {
9140 }
9141 }
9142 }
Romain Guy06882f82009-06-10 13:36:04 -07009143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009144 if (leakedSurface || killedApps) {
9145 // We managed to reclaim some memory, so get rid of the trouble
9146 // surface and ask the app to request another one.
9147 Log.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9148 if (surface != null) {
9149 surface.clear();
9150 win.mSurface = null;
9151 }
Romain Guy06882f82009-06-10 13:36:04 -07009152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 try {
9154 win.mClient.dispatchGetNewSurface();
9155 } catch (RemoteException e) {
9156 }
9157 }
9158 } finally {
9159 Binder.restoreCallingIdentity(callingIdentity);
9160 }
9161 }
Romain Guy06882f82009-06-10 13:36:04 -07009162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 private boolean updateFocusedWindowLocked(int mode) {
9164 WindowState newFocus = computeFocusedWindowLocked();
9165 if (mCurrentFocus != newFocus) {
9166 // This check makes sure that we don't already have the focus
9167 // change message pending.
9168 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9169 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9170 if (localLOGV) Log.v(
9171 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
9172 final WindowState oldFocus = mCurrentFocus;
9173 mCurrentFocus = newFocus;
9174 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -07009175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 final WindowState imWindow = mInputMethodWindow;
9177 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08009178 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08009180 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
9181 mLayoutNeeded = true;
9182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9184 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08009185 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9186 // Client will do the layout, but we need to assign layers
9187 // for handleNewWindowLocked() below.
9188 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 }
9190 }
Romain Guy06882f82009-06-10 13:36:04 -07009191
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08009192 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9193 mKeyWaiter.handleNewWindowLocked(newFocus);
9194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 return true;
9196 }
9197 return false;
9198 }
9199
9200 private WindowState computeFocusedWindowLocked() {
9201 WindowState result = null;
9202 WindowState win;
9203
9204 int i = mWindows.size() - 1;
9205 int nextAppIndex = mAppTokens.size()-1;
9206 WindowToken nextApp = nextAppIndex >= 0
9207 ? mAppTokens.get(nextAppIndex) : null;
9208
9209 while (i >= 0) {
9210 win = (WindowState)mWindows.get(i);
9211
9212 if (localLOGV || DEBUG_FOCUS) Log.v(
9213 TAG, "Looking for focus: " + i
9214 + " = " + win
9215 + ", flags=" + win.mAttrs.flags
9216 + ", canReceive=" + win.canReceiveKeys());
9217
9218 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -07009219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 // If this window's application has been removed, just skip it.
9221 if (thisApp != null && thisApp.removed) {
9222 i--;
9223 continue;
9224 }
Romain Guy06882f82009-06-10 13:36:04 -07009225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 // If there is a focused app, don't allow focus to go to any
9227 // windows below it. If this is an application window, step
9228 // through the app tokens until we find its app.
9229 if (thisApp != null && nextApp != null && thisApp != nextApp
9230 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
9231 int origAppIndex = nextAppIndex;
9232 while (nextAppIndex > 0) {
9233 if (nextApp == mFocusedApp) {
9234 // Whoops, we are below the focused app... no focus
9235 // for you!
9236 if (localLOGV || DEBUG_FOCUS) Log.v(
9237 TAG, "Reached focused app: " + mFocusedApp);
9238 return null;
9239 }
9240 nextAppIndex--;
9241 nextApp = mAppTokens.get(nextAppIndex);
9242 if (nextApp == thisApp) {
9243 break;
9244 }
9245 }
9246 if (thisApp != nextApp) {
9247 // Uh oh, the app token doesn't exist! This shouldn't
9248 // happen, but if it does we can get totally hosed...
9249 // so restart at the original app.
9250 nextAppIndex = origAppIndex;
9251 nextApp = mAppTokens.get(nextAppIndex);
9252 }
9253 }
9254
9255 // Dispatch to this window if it is wants key events.
9256 if (win.canReceiveKeys()) {
9257 if (DEBUG_FOCUS) Log.v(
9258 TAG, "Found focus @ " + i + " = " + win);
9259 result = win;
9260 break;
9261 }
9262
9263 i--;
9264 }
9265
9266 return result;
9267 }
9268
9269 private void startFreezingDisplayLocked() {
9270 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -07009271 // Freezing the display also suspends key event delivery, to
9272 // keep events from going astray while the display is reconfigured.
9273 // If someone has changed orientation again while the screen is
9274 // still frozen, the events will continue to be blocked while the
9275 // successive orientation change is processed. To prevent spurious
9276 // ANRs, we reset the event dispatch timeout in this case.
9277 synchronized (mKeyWaiter) {
9278 mKeyWaiter.mWasFrozen = true;
9279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280 return;
9281 }
Romain Guy06882f82009-06-10 13:36:04 -07009282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -07009284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 long now = SystemClock.uptimeMillis();
9286 //Log.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
9287 if (mFreezeGcPending != 0) {
9288 if (now > (mFreezeGcPending+1000)) {
9289 //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
9290 mH.removeMessages(H.FORCE_GC);
9291 Runtime.getRuntime().gc();
9292 mFreezeGcPending = now;
9293 }
9294 } else {
9295 mFreezeGcPending = now;
9296 }
Romain Guy06882f82009-06-10 13:36:04 -07009297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009298 mDisplayFrozen = true;
9299 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
9300 mNextAppTransition = WindowManagerPolicy.TRANSIT_NONE;
9301 mAppTransitionReady = true;
9302 }
Romain Guy06882f82009-06-10 13:36:04 -07009303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009304 if (PROFILE_ORIENTATION) {
9305 File file = new File("/data/system/frozen");
9306 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9307 }
9308 Surface.freezeDisplay(0);
9309 }
Romain Guy06882f82009-06-10 13:36:04 -07009310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 private void stopFreezingDisplayLocked() {
9312 if (!mDisplayFrozen) {
9313 return;
9314 }
Romain Guy06882f82009-06-10 13:36:04 -07009315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 mDisplayFrozen = false;
9317 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9318 if (PROFILE_ORIENTATION) {
9319 Debug.stopMethodTracing();
9320 }
9321 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -07009322
Chris Tate2ad63a92009-03-25 17:36:48 -07009323 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
9324 // too because regular key delivery processing should resume immediately.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 synchronized (mKeyWaiter) {
9326 mKeyWaiter.mWasFrozen = true;
9327 mKeyWaiter.notifyAll();
9328 }
9329
9330 // A little kludge: a lot could have happened while the
9331 // display was frozen, so now that we are coming back we
9332 // do a gc so that any remote references the system
9333 // processes holds on others can be released if they are
9334 // no longer needed.
9335 mH.removeMessages(H.FORCE_GC);
9336 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9337 2000);
Romain Guy06882f82009-06-10 13:36:04 -07009338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 mScreenFrozenLock.release();
9340 }
Romain Guy06882f82009-06-10 13:36:04 -07009341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 @Override
9343 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
9344 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
9345 != PackageManager.PERMISSION_GRANTED) {
9346 pw.println("Permission Denial: can't dump WindowManager from from pid="
9347 + Binder.getCallingPid()
9348 + ", uid=" + Binder.getCallingUid());
9349 return;
9350 }
Romain Guy06882f82009-06-10 13:36:04 -07009351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009352 synchronized(mWindowMap) {
9353 pw.println("Current Window Manager state:");
9354 for (int i=mWindows.size()-1; i>=0; i--) {
9355 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009356 pw.print(" Window #"); pw.print(i); pw.print(' ');
9357 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 w.dump(pw, " ");
9359 }
9360 if (mInputMethodDialogs.size() > 0) {
9361 pw.println(" ");
9362 pw.println(" Input method dialogs:");
9363 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
9364 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009365 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 }
9367 }
9368 if (mPendingRemove.size() > 0) {
9369 pw.println(" ");
9370 pw.println(" Remove pending for:");
9371 for (int i=mPendingRemove.size()-1; i>=0; i--) {
9372 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009373 pw.print(" Remove #"); pw.print(i); pw.print(' ');
9374 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 w.dump(pw, " ");
9376 }
9377 }
9378 if (mForceRemoves != null && mForceRemoves.size() > 0) {
9379 pw.println(" ");
9380 pw.println(" Windows force removing:");
9381 for (int i=mForceRemoves.size()-1; i>=0; i--) {
9382 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009383 pw.print(" Removing #"); pw.print(i); pw.print(' ');
9384 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 w.dump(pw, " ");
9386 }
9387 }
9388 if (mDestroySurface.size() > 0) {
9389 pw.println(" ");
9390 pw.println(" Windows waiting to destroy their surface:");
9391 for (int i=mDestroySurface.size()-1; i>=0; i--) {
9392 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009393 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
9394 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 w.dump(pw, " ");
9396 }
9397 }
9398 if (mLosingFocus.size() > 0) {
9399 pw.println(" ");
9400 pw.println(" Windows losing focus:");
9401 for (int i=mLosingFocus.size()-1; i>=0; i--) {
9402 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009403 pw.print(" Losing #"); pw.print(i); pw.print(' ');
9404 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 w.dump(pw, " ");
9406 }
9407 }
9408 if (mSessions.size() > 0) {
9409 pw.println(" ");
9410 pw.println(" All active sessions:");
9411 Iterator<Session> it = mSessions.iterator();
9412 while (it.hasNext()) {
9413 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009414 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009415 s.dump(pw, " ");
9416 }
9417 }
9418 if (mTokenMap.size() > 0) {
9419 pw.println(" ");
9420 pw.println(" All tokens:");
9421 Iterator<WindowToken> it = mTokenMap.values().iterator();
9422 while (it.hasNext()) {
9423 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009424 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 token.dump(pw, " ");
9426 }
9427 }
9428 if (mTokenList.size() > 0) {
9429 pw.println(" ");
9430 pw.println(" Window token list:");
9431 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009432 pw.print(" #"); pw.print(i); pw.print(": ");
9433 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009434 }
9435 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07009436 if (mWallpaperTokens.size() > 0) {
9437 pw.println(" ");
9438 pw.println(" Wallpaper tokens:");
9439 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
9440 WindowToken token = mWallpaperTokens.get(i);
9441 pw.print(" Wallpaper #"); pw.print(i);
9442 pw.print(' '); pw.print(token); pw.println(':');
9443 token.dump(pw, " ");
9444 }
9445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 if (mAppTokens.size() > 0) {
9447 pw.println(" ");
9448 pw.println(" Application tokens in Z order:");
9449 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009450 pw.print(" App #"); pw.print(i); pw.print(": ");
9451 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 }
9453 }
9454 if (mFinishedStarting.size() > 0) {
9455 pw.println(" ");
9456 pw.println(" Finishing start of application tokens:");
9457 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
9458 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009459 pw.print(" Finished Starting #"); pw.print(i);
9460 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 token.dump(pw, " ");
9462 }
9463 }
9464 if (mExitingTokens.size() > 0) {
9465 pw.println(" ");
9466 pw.println(" Exiting tokens:");
9467 for (int i=mExitingTokens.size()-1; i>=0; i--) {
9468 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009469 pw.print(" Exiting #"); pw.print(i);
9470 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 token.dump(pw, " ");
9472 }
9473 }
9474 if (mExitingAppTokens.size() > 0) {
9475 pw.println(" ");
9476 pw.println(" Exiting application tokens:");
9477 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
9478 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009479 pw.print(" Exiting App #"); pw.print(i);
9480 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 token.dump(pw, " ");
9482 }
9483 }
9484 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009485 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
9486 pw.print(" mLastFocus="); pw.println(mLastFocus);
9487 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
9488 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
9489 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -07009490 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009491 pw.print(" mInTouchMode="); pw.println(mInTouchMode);
9492 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
9493 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
9494 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
9495 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009496 if (mDimAnimator != null) {
9497 mDimAnimator.printTo(pw);
9498 } else {
9499 pw.print( " no DimAnimator ");
9500 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009501 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009502 pw.print(mInputMethodAnimLayerAdjustment);
9503 pw.print(" mWallpaperAnimLayerAdjustment=");
9504 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009505 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
9506 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
9507 pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
9508 pw.print(" mRotation="); pw.print(mRotation);
9509 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
9510 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
9511 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
9512 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
9513 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
9514 pw.print(" mNextAppTransition=0x");
9515 pw.print(Integer.toHexString(mNextAppTransition));
9516 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
9517 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
9518 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
9519 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
9520 if (mOpeningApps.size() > 0) {
9521 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
9522 }
9523 if (mClosingApps.size() > 0) {
9524 pw.print(" mClosingApps="); pw.println(mClosingApps);
9525 }
9526 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
9527 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 pw.println(" KeyWaiter state:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009529 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
9530 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
9531 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
9532 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
9533 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
9534 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009535 }
9536 }
9537
9538 public void monitor() {
9539 synchronized (mWindowMap) { }
9540 synchronized (mKeyguardDisabled) { }
9541 synchronized (mKeyWaiter) { }
9542 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009543
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07009544 public void virtualKeyFeedback(KeyEvent event) {
9545 mPolicy.keyFeedbackFromInput(event);
9546 }
9547
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009548 /**
9549 * DimAnimator class that controls the dim animation. This holds the surface and
9550 * all state used for dim animation.
9551 */
9552 private static class DimAnimator {
9553 Surface mDimSurface;
9554 boolean mDimShown = false;
9555 float mDimCurrentAlpha;
9556 float mDimTargetAlpha;
9557 float mDimDeltaPerMs;
9558 long mLastDimAnimTime;
9559
9560 DimAnimator (SurfaceSession session) {
9561 if (mDimSurface == null) {
9562 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
9563 + mDimSurface + ": CREATE");
9564 try {
9565 mDimSurface = new Surface(session, 0, -1, 16, 16, PixelFormat.OPAQUE,
9566 Surface.FX_SURFACE_DIM);
9567 } catch (Exception e) {
9568 Log.e(TAG, "Exception creating Dim surface", e);
9569 }
9570 }
9571 }
9572
9573 /**
9574 * Show the dim surface.
9575 */
9576 void show(int dw, int dh) {
9577 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
9578 dw + "x" + dh + ")");
9579 mDimShown = true;
9580 try {
9581 mDimSurface.setPosition(0, 0);
9582 mDimSurface.setSize(dw, dh);
9583 mDimSurface.show();
9584 } catch (RuntimeException e) {
9585 Log.w(TAG, "Failure showing dim surface", e);
9586 }
9587 }
9588
9589 /**
9590 * Set's the dim surface's layer and update dim parameters that will be used in
9591 * {@link updateSurface} after all windows are examined.
9592 */
9593 void updateParameters(WindowState w, long currentTime) {
9594 mDimSurface.setLayer(w.mAnimLayer-1);
9595
9596 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
9597 if (SHOW_TRANSACTIONS) Log.i(TAG, "layer=" + (w.mAnimLayer-1) + ", target=" + target);
9598 if (mDimTargetAlpha != target) {
9599 // If the desired dim level has changed, then
9600 // start an animation to it.
9601 mLastDimAnimTime = currentTime;
9602 long duration = (w.mAnimating && w.mAnimation != null)
9603 ? w.mAnimation.computeDurationHint()
9604 : DEFAULT_DIM_DURATION;
9605 if (target > mDimTargetAlpha) {
9606 // This is happening behind the activity UI,
9607 // so we can make it run a little longer to
9608 // give a stronger impression without disrupting
9609 // the user.
9610 duration *= DIM_DURATION_MULTIPLIER;
9611 }
9612 if (duration < 1) {
9613 // Don't divide by zero
9614 duration = 1;
9615 }
9616 mDimTargetAlpha = target;
9617 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
9618 }
9619 }
9620
9621 /**
9622 * Updating the surface's alpha. Returns true if the animation continues, or returns
9623 * false when the animation is finished and the dim surface is hidden.
9624 */
9625 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
9626 if (!dimming) {
9627 if (mDimTargetAlpha != 0) {
9628 mLastDimAnimTime = currentTime;
9629 mDimTargetAlpha = 0;
9630 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
9631 }
9632 }
9633
9634 boolean animating = false;
9635 if (mLastDimAnimTime != 0) {
9636 mDimCurrentAlpha += mDimDeltaPerMs
9637 * (currentTime-mLastDimAnimTime);
9638 boolean more = true;
9639 if (displayFrozen) {
9640 // If the display is frozen, there is no reason to animate.
9641 more = false;
9642 } else if (mDimDeltaPerMs > 0) {
9643 if (mDimCurrentAlpha > mDimTargetAlpha) {
9644 more = false;
9645 }
9646 } else if (mDimDeltaPerMs < 0) {
9647 if (mDimCurrentAlpha < mDimTargetAlpha) {
9648 more = false;
9649 }
9650 } else {
9651 more = false;
9652 }
9653
9654 // Do we need to continue animating?
9655 if (more) {
9656 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
9657 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
9658 mLastDimAnimTime = currentTime;
9659 mDimSurface.setAlpha(mDimCurrentAlpha);
9660 animating = true;
9661 } else {
9662 mDimCurrentAlpha = mDimTargetAlpha;
9663 mLastDimAnimTime = 0;
9664 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
9665 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
9666 mDimSurface.setAlpha(mDimCurrentAlpha);
9667 if (!dimming) {
9668 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface
9669 + ": HIDE");
9670 try {
9671 mDimSurface.hide();
9672 } catch (RuntimeException e) {
9673 Log.w(TAG, "Illegal argument exception hiding dim surface");
9674 }
9675 mDimShown = false;
9676 }
9677 }
9678 }
9679 return animating;
9680 }
9681
9682 public void printTo(PrintWriter pw) {
9683 pw.print(" mDimShown="); pw.print(mDimShown);
9684 pw.print(" current="); pw.print(mDimCurrentAlpha);
9685 pw.print(" target="); pw.print(mDimTargetAlpha);
9686 pw.print(" delta="); pw.print(mDimDeltaPerMs);
9687 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
9688 }
9689 }
9690
9691 /**
9692 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
9693 * This is used for opening/closing transition for apps in compatible mode.
9694 */
9695 private static class FadeInOutAnimation extends Animation {
9696 int mWidth;
9697 boolean mFadeIn;
9698
9699 public FadeInOutAnimation(boolean fadeIn) {
9700 setInterpolator(new AccelerateInterpolator());
9701 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
9702 mFadeIn = fadeIn;
9703 }
9704
9705 @Override
9706 protected void applyTransformation(float interpolatedTime, Transformation t) {
9707 float x = interpolatedTime;
9708 if (!mFadeIn) {
9709 x = 1.0f - x; // reverse the interpolation for fade out
9710 }
9711 if (x < 0.5) {
9712 // move the window out of the screen.
9713 t.getMatrix().setTranslate(mWidth, 0);
9714 } else {
9715 t.getMatrix().setTranslate(0, 0);// show
9716 t.setAlpha((x - 0.5f) * 2);
9717 }
9718 }
9719
9720 @Override
9721 public void initialize(int width, int height, int parentWidth, int parentHeight) {
9722 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
9723 mWidth = width;
9724 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009725
9726 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07009727 public int getZAdjustment() {
9728 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009729 }
9730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731}