OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / wm / WindowManagerService.java
1 /*
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
17 package com.android.server.wm;
18
19 import android.Manifest;
20 import android.animation.ValueAnimator;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.ActivityManagerInternal;
25 import android.app.ActivityManagerNative;
26 import android.app.AppOpsManager;
27 import android.app.IActivityManager;
28 import android.app.Notification;
29 import android.app.NotificationManager;
30 import android.app.PendingIntent;
31 import android.app.admin.DevicePolicyManager;
32 import android.content.BroadcastReceiver;
33 import android.content.ContentResolver;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.content.pm.ActivityInfo;
38 import android.content.pm.PackageManager;
39 import android.content.res.CompatibilityInfo;
40 import android.content.res.Configuration;
41 import android.database.ContentObserver;
42 import android.graphics.Bitmap;
43 import android.graphics.PixelFormat;
44 import android.graphics.Matrix;
45 import android.graphics.Point;
46 import android.graphics.Rect;
47 import android.graphics.RectF;
48 import android.graphics.Region;
49 import android.hardware.display.DisplayManager;
50 import android.hardware.display.DisplayManagerInternal;
51 import android.hardware.input.InputManager;
52 import android.net.Uri;
53 import android.os.Binder;
54 import android.os.Build;
55 import android.os.Bundle;
56 import android.os.Debug;
57 import android.os.Handler;
58 import android.os.IBinder;
59 import android.os.IRemoteCallback;
60 import android.os.Looper;
61 import android.os.Message;
62 import android.os.Parcel;
63 import android.os.ParcelFileDescriptor;
64 import android.os.PowerManager;
65 import android.os.PowerManagerInternal;
66 import android.os.Process;
67 import android.os.RemoteException;
68 import android.os.ServiceManager;
69 import android.os.StrictMode;
70 import android.os.SystemClock;
71 import android.os.SystemProperties;
72 import android.os.SystemService;
73 import android.os.Trace;
74 import android.os.UserHandle;
75 import android.os.WorkSource;
76 import android.provider.Settings;
77 import android.util.ArraySet;
78 import android.util.DisplayMetrics;
79 import android.util.EventLog;
80 import android.util.Log;
81 import android.util.Pair;
82 import android.util.Slog;
83 import android.util.SparseArray;
84 import android.util.SparseIntArray;
85 import android.util.TimeUtils;
86 import android.util.TypedValue;
87 import android.view.AppTransitionAnimationSpec;
88 import android.view.Choreographer;
89 import android.view.Display;
90 import android.view.DisplayInfo;
91 import android.view.Gravity;
92 import android.view.PointerIcon;
93 import android.view.IAppTransitionAnimationSpecsFuture;
94 import android.view.IApplicationToken;
95 import android.view.IDockedStackListener;
96 import android.view.IInputFilter;
97 import android.view.IOnKeyguardExitResult;
98 import android.view.IRotationWatcher;
99 import android.view.IWindow;
100 import android.view.IWindowId;
101 import android.view.IWindowManager;
102 import android.view.IWindowSession;
103 import android.view.IWindowSessionCallback;
104 import android.view.InputChannel;
105 import android.view.InputDevice;
106 import android.view.InputEvent;
107 import android.view.InputEventReceiver;
108 import android.view.KeyEvent;
109 import android.view.MagnificationSpec;
110 import android.view.MotionEvent;
111 import android.view.Surface;
112 import android.view.Surface.OutOfResourcesException;
113 import android.view.SurfaceControl;
114 import android.view.SurfaceSession;
115 import android.view.View;
116 import android.view.WindowContentFrameStats;
117 import android.view.WindowManager;
118 import android.view.WindowManager.LayoutParams;
119 import android.view.WindowManagerGlobal;
120 import android.view.WindowManagerInternal;
121 import android.view.WindowManagerPolicy;
122 import android.view.WindowManagerPolicy.PointerEventListener;
123 import android.view.animation.Animation;
124 import android.view.inputmethod.InputMethodManagerInternal;
125
126 import com.android.internal.R;
127 import com.android.internal.app.IAssistScreenshotReceiver;
128 import com.android.internal.os.IResultReceiver;
129 import com.android.internal.policy.IShortcutService;
130 import com.android.internal.util.ArrayUtils;
131 import com.android.internal.util.FastPrintWriter;
132 import com.android.internal.view.IInputContext;
133 import com.android.internal.view.IInputMethodClient;
134 import com.android.internal.view.IInputMethodManager;
135 import com.android.internal.view.WindowManagerPolicyThread;
136 import com.android.server.AttributeCache;
137 import com.android.server.DisplayThread;
138 import com.android.server.EventLogTags;
139 import com.android.server.FgThread;
140 import com.android.server.LocalServices;
141 import com.android.server.UiThread;
142 import com.android.server.Watchdog;
143 import com.android.server.input.InputManagerService;
144 import com.android.server.policy.PhoneWindowManager;
145 import com.android.server.power.ShutdownThread;
146
147 import java.io.BufferedWriter;
148 import java.io.DataInputStream;
149 import java.io.File;
150 import java.io.FileDescriptor;
151 import java.io.FileInputStream;
152 import java.io.FileNotFoundException;
153 import java.io.IOException;
154 import java.io.OutputStream;
155 import java.io.OutputStreamWriter;
156 import java.io.PrintWriter;
157 import java.io.StringWriter;
158 import java.lang.annotation.Retention;
159 import java.lang.annotation.RetentionPolicy;
160 import java.net.Socket;
161 import java.text.DateFormat;
162 import java.util.ArrayList;
163 import java.util.Arrays;
164 import java.util.Date;
165 import java.util.HashMap;
166 import java.util.Iterator;
167 import java.util.List;
168
169 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
170 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
171 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
172 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
173 import static android.app.StatusBarManager.DISABLE_MASK;
174 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
175 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
176 import static android.view.WindowManager.DOCKED_BOTTOM;
177 import static android.view.WindowManager.DOCKED_INVALID;
178 import static android.view.WindowManager.DOCKED_TOP;
179 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
180 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
181 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
182 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
183 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
184 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
185 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
186 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
187 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
188 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
189 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
190 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
191 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
192 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
193 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
194 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
195 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
196 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
197 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
198 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
199 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
200 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
201 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
202 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
203 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
204 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
205 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
206 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
207 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
208 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
209 import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
210 import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
211 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
212 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
213 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
214 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
215 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
216 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
217 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
218 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_ORIENTATION;
219 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
220 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
221 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
222 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
223 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
224 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
225 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
226 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
227 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
228 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
229 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
230 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
231 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
232 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
233 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
234 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
235 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
236 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
237 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
238 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
239 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
240 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
241 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
242 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
243 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
244 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
245 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
246 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
247 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
248 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
249 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
250 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
251 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
252
253 /** {@hide} */
254 public class WindowManagerService extends IWindowManager.Stub
255         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
256     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
257
258     static final int LAYOUT_REPEAT_THRESHOLD = 4;
259
260     static final boolean PROFILE_ORIENTATION = false;
261     static final boolean localLOGV = DEBUG;
262
263     /** How much to multiply the policy's type layer, to reserve room
264      * for multiple windows of the same type and Z-ordering adjustment
265      * with TYPE_LAYER_OFFSET. */
266     static final int TYPE_LAYER_MULTIPLIER = 10000;
267
268     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
269      * or below others in the same layer. */
270     static final int TYPE_LAYER_OFFSET = 1000;
271
272     /** How much to increment the layer for each window, to reserve room
273      * for effect surfaces between them.
274      */
275     static final int WINDOW_LAYER_MULTIPLIER = 5;
276
277     /**
278      * Dim surface layer is immediately below target window.
279      */
280     static final int LAYER_OFFSET_DIM = 1;
281
282     /**
283      * Animation thumbnail is as far as possible below the window above
284      * the thumbnail (or in other words as far as possible above the window
285      * below it).
286      */
287     static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
288
289     /** The maximum length we will accept for a loaded animation duration:
290      * this is 10 seconds.
291      */
292     static final int MAX_ANIMATION_DURATION = 10 * 1000;
293
294     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
295     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
296
297     /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
298     static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
299
300     /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
301     static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
302
303     /** Amount of time to allow a last ANR message to exist before freeing the memory. */
304     static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
305     /**
306      * If true, the window manager will do its own custom freezing and general
307      * management of the screen during rotation.
308      */
309     static final boolean CUSTOM_SCREEN_ROTATION = true;
310
311     // Maximum number of milliseconds to wait for input devices to be enumerated before
312     // proceding with safe mode detection.
313     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
314
315     // Default input dispatching timeout in nanoseconds.
316     static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
317
318     // Poll interval in milliseconds for watching boot animation finished.
319     private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
320
321     // The name of the boot animation service in init.rc.
322     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
323
324     static final int UPDATE_FOCUS_NORMAL = 0;
325     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
326     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
327     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
328
329     private static final String SYSTEM_SECURE = "ro.secure";
330     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
331
332     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
333     private static final String SIZE_OVERRIDE = "ro.config.size_override";
334
335     private static final int MAX_SCREENSHOT_RETRIES = 3;
336
337     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
338
339     // Used to indicate that if there is already a transition set, it should be preserved when
340     // trying to apply a new one.
341     private static final boolean ALWAYS_KEEP_CURRENT = true;
342
343     private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
344
345     private static final String PROPERTY_BUILD_DATE_UTC = "ro.build.date.utc";
346
347     // Enums for animation scale update types.
348     @Retention(RetentionPolicy.SOURCE)
349     @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
350     private @interface UpdateAnimationScaleMode {};
351     private static final int WINDOW_ANIMATION_SCALE = 0;
352     private static final int TRANSITION_ANIMATION_SCALE = 1;
353     private static final int ANIMATION_DURATION_SCALE = 2;
354
355     final private KeyguardDisableHandler mKeyguardDisableHandler;
356
357     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
358         @Override
359         public void onReceive(Context context, Intent intent) {
360             final String action = intent.getAction();
361             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
362                 mKeyguardDisableHandler.sendEmptyMessage(
363                     KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
364             }
365         }
366     };
367     final WindowSurfacePlacer mWindowPlacerLocked;
368
369     /**
370      * Current user when multi-user is enabled. Don't show windows of
371      * non-current user. Also see mCurrentProfileIds.
372      */
373     int mCurrentUserId;
374     /**
375      * Users that are profiles of the current user. These are also allowed to show windows
376      * on the current user.
377      */
378     int[] mCurrentProfileIds = new int[] {};
379
380     final Context mContext;
381
382     final boolean mHaveInputMethods;
383
384     final boolean mHasPermanentDpad;
385     final long mDrawLockTimeoutMillis;
386     final boolean mAllowAnimationsInLowPowerMode;
387
388     final boolean mAllowBootMessages;
389
390     final boolean mLimitedAlphaCompositing;
391
392     final WindowManagerPolicy mPolicy = new PhoneWindowManager();
393
394     final IActivityManager mActivityManager;
395     final ActivityManagerInternal mAmInternal;
396
397     final AppOpsManager mAppOps;
398
399     final DisplaySettings mDisplaySettings;
400
401     /**
402      * All currently active sessions with clients.
403      */
404     final ArraySet<Session> mSessions = new ArraySet<>();
405
406     /**
407      * Mapping from an IWindow IBinder to the server's Window object.
408      * This is also used as the lock for all of our state.
409      * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
410      */
411     final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
412
413     /**
414      * Mapping from a token IBinder to a WindowToken object.
415      */
416     final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>();
417
418     /**
419      * List of window tokens that have finished starting their application,
420      * and now need to have the policy remove their windows.
421      */
422     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
423
424     /**
425      * List of window tokens that have finished drawing their own windows and
426      * no longer need to show any saved surfaces. Windows that's still showing
427      * saved surfaces will be cleaned up after next animation pass.
428      */
429     final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
430
431     /**
432      * List of app window tokens that are waiting for replacing windows. If the
433      * replacement doesn't come in time the stale windows needs to be disposed of.
434      */
435     final ArrayList<AppWindowToken> mReplacingWindowTimeouts = new ArrayList<>();
436
437     /**
438      * The input consumer added to the window manager which consumes input events to windows below
439      * it.
440      */
441     InputConsumerImpl mInputConsumer;
442
443     /**
444      * The input consumer added to the window manager before all wallpaper windows.
445      */
446     InputConsumerImpl mWallpaperInputConsumer;
447
448     /**
449      * Windows that are being resized.  Used so we can tell the client about
450      * the resize after closing the transaction in which we resized the
451      * underlying surface.
452      */
453     final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
454
455     /**
456      * Windows whose animations have ended and now must be removed.
457      */
458     final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
459
460     /**
461      * Used when processing mPendingRemove to avoid working on the original array.
462      */
463     WindowState[] mPendingRemoveTmp = new WindowState[20];
464
465     /**
466      * Windows whose surface should be destroyed.
467      */
468     final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
469
470     /**
471      * Windows with a preserved surface waiting to be destroyed. These windows
472      * are going through a surface change. We keep the old surface around until
473      * the first frame on the new surface finishes drawing.
474      */
475     final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
476
477     /**
478      * Windows that have lost input focus and are waiting for the new
479      * focus window to be displayed before they are told about this.
480      */
481     ArrayList<WindowState> mLosingFocus = new ArrayList<>();
482
483     /**
484      * This is set when we have run out of memory, and will either be an empty
485      * list or contain windows that need to be force removed.
486      */
487     final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
488
489     /**
490      * Windows that clients are waiting to have drawn.
491      */
492     ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
493     /**
494      * And the callback to make when they've all been drawn.
495      */
496     Runnable mWaitingForDrawnCallback;
497
498     /**
499      * Used when rebuilding window list to keep track of windows that have
500      * been removed.
501      */
502     WindowState[] mRebuildTmp = new WindowState[20];
503
504     /**
505      * Stores for each user whether screencapture is disabled
506      * This array is essentially a cache for all userId for
507      * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
508      */
509     SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
510
511     IInputMethodManager mInputMethodManager;
512
513     AccessibilityController mAccessibilityController;
514
515     final SurfaceSession mFxSession;
516     Watermark mWatermark;
517     StrictModeFlash mStrictModeFlash;
518     CircularDisplayMask mCircularDisplayMask;
519     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
520
521     final float[] mTmpFloats = new float[9];
522     final Rect mTmpRect = new Rect();
523     final Rect mTmpRect2 = new Rect();
524     final Rect mTmpRect3 = new Rect();
525     final RectF mTmpRectF = new RectF();
526
527     final Matrix mTmpTransform = new Matrix();
528
529     boolean mDisplayReady;
530     boolean mSafeMode;
531     boolean mDisplayEnabled = false;
532     boolean mSystemBooted = false;
533     boolean mForceDisplayEnabled = false;
534     boolean mShowingBootMessages = false;
535     boolean mBootAnimationStopped = false;
536
537     // Following variables are for debugging screen wakelock only.
538     WindowState mLastWakeLockHoldingWindow = null;
539     WindowState mLastWakeLockObscuringWindow = null;
540
541     /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
542      * LAST_ANR_LIFETIME_DURATION_MSECS */
543     String mLastANRState;
544
545     /** All DisplayContents in the world, kept here */
546     SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
547
548     int mRotation = 0;
549     int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
550     boolean mAltOrientation = false;
551
552     private boolean mKeyguardWaitingForActivityDrawn;
553
554     int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
555     Rect mDockedStackCreateBounds;
556
557     private final SparseIntArray mTmpTaskIds = new SparseIntArray();
558
559     private final ArrayList<Integer> mChangedStackList = new ArrayList();
560
561     boolean mForceResizableTasks = false;
562
563     int getDragLayerLocked() {
564         return mPolicy.windowTypeToLayerLw(LayoutParams.TYPE_DRAG) * TYPE_LAYER_MULTIPLIER
565                 + TYPE_LAYER_OFFSET;
566     }
567
568     class RotationWatcher {
569         IRotationWatcher watcher;
570         IBinder.DeathRecipient deathRecipient;
571         RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) {
572             watcher = w;
573             deathRecipient = d;
574         }
575     }
576     ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
577     int mDeferredRotationPauseCount;
578
579     int mSystemDecorLayer = 0;
580     final Rect mScreenRect = new Rect();
581
582     boolean mDisplayFrozen = false;
583     long mDisplayFreezeTime = 0;
584     int mLastDisplayFreezeDuration = 0;
585     Object mLastFinishedFreezeSource = null;
586     boolean mWaitingForConfig = false;
587
588     final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
589     final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
590     final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
591     int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
592
593     boolean mClientFreezingScreen = false;
594     int mAppsFreezingScreen = 0;
595     int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
596     int mLastKeyguardForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
597
598     int mLayoutSeq = 0;
599
600     // Last systemUiVisibility we received from status bar.
601     int mLastStatusBarVisibility = 0;
602     // Last systemUiVisibility we dispatched to windows.
603     int mLastDispatchedSystemUiVisibility = 0;
604
605     // State while inside of layoutAndPlaceSurfacesLocked().
606     boolean mFocusMayChange;
607
608     Configuration mCurConfiguration = new Configuration();
609
610     // This is held as long as we have the screen frozen, to give us time to
611     // perform a rotation animation when turning off shows the lock screen which
612     // changes the orientation.
613     private final PowerManager.WakeLock mScreenFrozenLock;
614
615     final AppTransition mAppTransition;
616     boolean mSkipAppTransitionAnimation = false;
617
618     final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
619     final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
620
621     boolean mIsTouchDevice;
622
623     final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
624     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
625     final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
626     final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
627
628     final H mH = new H();
629
630     final Choreographer mChoreographer = Choreographer.getInstance();
631
632     WindowState mCurrentFocus = null;
633     WindowState mLastFocus = null;
634
635     /** This just indicates the window the input method is on top of, not
636      * necessarily the window its input is going to. */
637     WindowState mInputMethodTarget = null;
638
639     /** If true hold off on modifying the animation layer of mInputMethodTarget */
640     boolean mInputMethodTargetWaitingAnim;
641
642     WindowState mInputMethodWindow = null;
643     final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
644
645     /** Temporary list for comparison. Always clear this after use so we don't end up with
646      * orphaned windows references */
647     final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
648
649     boolean mHardKeyboardAvailable;
650     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
651     SettingsObserver mSettingsObserver;
652
653     private final class SettingsObserver extends ContentObserver {
654         private final Uri mDisplayInversionEnabledUri =
655                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
656         private final Uri mWindowAnimationScaleUri =
657                 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
658         private final Uri mTransitionAnimationScaleUri =
659                 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
660         private final Uri mAnimationDurationScaleUri =
661                 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
662
663         public SettingsObserver() {
664             super(new Handler());
665             ContentResolver resolver = mContext.getContentResolver();
666             resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
667                     UserHandle.USER_ALL);
668             resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
669                     UserHandle.USER_ALL);
670             resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
671                     UserHandle.USER_ALL);
672             resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
673                     UserHandle.USER_ALL);
674         }
675
676         @Override
677         public void onChange(boolean selfChange, Uri uri) {
678             if (uri == null) {
679                 return;
680             }
681
682             if (mDisplayInversionEnabledUri.equals(uri)) {
683                 updateCircularDisplayMaskIfNeeded();
684             } else {
685                 @UpdateAnimationScaleMode
686                 final int mode;
687                 if (mWindowAnimationScaleUri.equals(uri)) {
688                     mode = WINDOW_ANIMATION_SCALE;
689                 } else if (mTransitionAnimationScaleUri.equals(uri)) {
690                     mode = TRANSITION_ANIMATION_SCALE;
691                 } else if (mAnimationDurationScaleUri.equals(uri)) {
692                     mode = ANIMATION_DURATION_SCALE;
693                 } else {
694                     // Ignoring unrecognized content changes
695                     return;
696                 }
697                 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
698                 mH.sendMessage(m);
699             }
700         }
701     }
702
703     WallpaperController mWallpaperControllerLocked;
704
705     final WindowLayersController mLayersController;
706
707     boolean mAnimateWallpaperWithTarget;
708
709     AppWindowToken mFocusedApp = null;
710
711     PowerManager mPowerManager;
712     PowerManagerInternal mPowerManagerInternal;
713
714     float mWindowAnimationScaleSetting = 1.0f;
715     float mTransitionAnimationScaleSetting = 1.0f;
716     float mAnimatorDurationScaleSetting = 1.0f;
717     boolean mAnimationsDisabled = false;
718
719     final InputManagerService mInputManager;
720     final DisplayManagerInternal mDisplayManagerInternal;
721     final DisplayManager mDisplayManager;
722     final Display[] mDisplays;
723
724     // Who is holding the screen on.
725     Session mHoldingScreenOn;
726     PowerManager.WakeLock mHoldingScreenWakeLock;
727
728     boolean mTurnOnScreen;
729
730     // Whether or not a layout can cause a wake up when theater mode is enabled.
731     boolean mAllowTheaterModeWakeFromLayout;
732
733     TaskPositioner mTaskPositioner;
734     DragState mDragState = null;
735
736     // For frozen screen animations.
737     int mExitAnimId, mEnterAnimId;
738
739     boolean mAnimationScheduled;
740
741     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
742      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
743     int mTransactionSequence;
744
745     final WindowAnimator mAnimator;
746
747     private final BoundsAnimationController mBoundsAnimationController;
748
749     SparseArray<Task> mTaskIdToTask = new SparseArray<>();
750
751     /** All of the TaskStacks in the window manager, unordered. For an ordered list call
752      * DisplayContent.getStacks(). */
753     SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
754
755     private final PointerEventDispatcher mPointerEventDispatcher;
756
757     private WindowContentFrameStats mTempWindowRenderStats;
758
759     final class DragInputEventReceiver extends InputEventReceiver {
760         // Set, if stylus button was down at the start of the drag.
761         private boolean mStylusButtonDownAtStart;
762         // Indicates the first event to check for button state.
763         private boolean mIsStartEvent = true;
764
765         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
766             super(inputChannel, looper);
767         }
768
769         @Override
770         public void onInputEvent(InputEvent event) {
771             boolean handled = false;
772             try {
773                 if (event instanceof MotionEvent
774                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
775                         && mDragState != null) {
776                     final MotionEvent motionEvent = (MotionEvent)event;
777                     boolean endDrag = false;
778                     final float newX = motionEvent.getRawX();
779                     final float newY = motionEvent.getRawY();
780                     final boolean isStylusButtonDown =
781                             (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0;
782
783                     if (mIsStartEvent) {
784                         if (isStylusButtonDown) {
785                             // First event and the button was down, check for the button being
786                             // lifted in the future, if that happens we'll drop the item.
787                             mStylusButtonDownAtStart = true;
788                         }
789                         mIsStartEvent = false;
790                     }
791
792                     switch (motionEvent.getAction()) {
793                     case MotionEvent.ACTION_DOWN: {
794                         if (DEBUG_DRAG) {
795                             Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer");
796                         }
797                     } break;
798
799                     case MotionEvent.ACTION_MOVE: {
800                         if (mStylusButtonDownAtStart && !isStylusButtonDown) {
801                             if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at "
802                                     + newX + "," + newY);
803                             synchronized (mWindowMap) {
804                                 endDrag = mDragState.notifyDropLw(newX, newY);
805                             }
806                         } else {
807                             synchronized (mWindowMap) {
808                                 // move the surface and tell the involved window(s) where we are
809                                 mDragState.notifyMoveLw(newX, newY);
810                             }
811                         }
812                     } break;
813
814                     case MotionEvent.ACTION_UP: {
815                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at "
816                                 + newX + "," + newY);
817                         synchronized (mWindowMap) {
818                             endDrag = mDragState.notifyDropLw(newX, newY);
819                         }
820                     } break;
821
822                     case MotionEvent.ACTION_CANCEL: {
823                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!");
824                         endDrag = true;
825                     } break;
826                     }
827
828                     if (endDrag) {
829                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
830                         // tell all the windows that the drag has ended
831                         synchronized (mWindowMap) {
832                             mDragState.endDragLw();
833                         }
834                         mStylusButtonDownAtStart = false;
835                         mIsStartEvent = true;
836                     }
837
838                     handled = true;
839                 }
840             } catch (Exception e) {
841                 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
842             } finally {
843                 finishInputEvent(event, handled);
844             }
845         }
846     }
847
848     /**
849      * Whether the UI is currently running in touch mode (not showing
850      * navigational focus because the user is directly pressing the screen).
851      */
852     boolean mInTouchMode;
853
854     private ViewServer mViewServer;
855     final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
856     boolean mWindowsChanged = false;
857
858     public interface WindowChangeListener {
859         public void windowsChanged();
860         public void focusChanged();
861     }
862
863     final Configuration mTempConfiguration = new Configuration();
864
865     // The desired scaling factor for compatible apps.
866     float mCompatibleScreenScale;
867
868     // If true, only the core apps and services are being launched because the device
869     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
870     // For example, when this flag is true, there will be no wallpaper service.
871     final boolean mOnlyCore;
872
873     // List of clients without a transtiton animation that we notify once we are done transitioning
874     // since they won't be notified through the app window animator.
875     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
876
877     // List of displays to reconfigure after configuration changes.
878     // Some of the information reported for a display is dependent on resources to do the right
879     // calculations. For example, {@link DisplayInfo#smallestNominalAppWidth} and company are
880     // dependent on the height and width of the status and nav bar which change depending on the
881     // current configuration.
882     private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList();
883
884     /** Listener to notify activity manager about app transitions. */
885     private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
886             = new WindowManagerInternal.AppTransitionListener() {
887
888         @Override
889         public void onAppTransitionCancelledLocked() {
890             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
891         }
892
893         @Override
894         public void onAppTransitionFinishedLocked(IBinder token) {
895             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
896             AppWindowToken atoken = findAppWindowToken(token);
897             if (atoken == null) {
898                 return;
899             }
900             if (atoken.mLaunchTaskBehind) {
901                 try {
902                     mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
903                 } catch (RemoteException e) {
904                 }
905                 atoken.mLaunchTaskBehind = false;
906             } else {
907                 atoken.updateReportedVisibilityLocked();
908                 if (atoken.mEnteringAnimation) {
909                     atoken.mEnteringAnimation = false;
910                     try {
911                         mActivityManager.notifyEnterAnimationComplete(atoken.token);
912                     } catch (RemoteException e) {
913                     }
914                 }
915             }
916         }
917     };
918
919     public static WindowManagerService main(final Context context,
920             final InputManagerService im,
921             final boolean haveInputMethods, final boolean showBootMsgs,
922             final boolean onlyCore) {
923         final WindowManagerService[] holder = new WindowManagerService[1];
924         DisplayThread.getHandler().runWithScissors(new Runnable() {
925             @Override
926             public void run() {
927                 holder[0] = new WindowManagerService(context, im,
928                         haveInputMethods, showBootMsgs, onlyCore);
929             }
930         }, 0);
931         return holder[0];
932     }
933
934     private void initPolicy() {
935         UiThread.getHandler().runWithScissors(new Runnable() {
936             @Override
937             public void run() {
938                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
939
940                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
941             }
942         }, 0);
943     }
944
945     private WindowManagerService(Context context, InputManagerService inputManager,
946             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
947         mContext = context;
948         mHaveInputMethods = haveInputMethods;
949         mAllowBootMessages = showBootMsgs;
950         mOnlyCore = onlyCore;
951         mLimitedAlphaCompositing = context.getResources().getBoolean(
952                 com.android.internal.R.bool.config_sf_limitedAlpha);
953         mHasPermanentDpad = context.getResources().getBoolean(
954                 com.android.internal.R.bool.config_hasPermanentDpad);
955         mInTouchMode = context.getResources().getBoolean(
956                 com.android.internal.R.bool.config_defaultInTouchMode);
957         mDrawLockTimeoutMillis = context.getResources().getInteger(
958                 com.android.internal.R.integer.config_drawLockTimeoutMillis);
959         mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
960                 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
961         mInputManager = inputManager; // Must be before createDisplayContentLocked.
962         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
963         mDisplaySettings = new DisplaySettings();
964         mDisplaySettings.readSettingsLocked();
965
966         mWallpaperControllerLocked = new WallpaperController(this);
967         mWindowPlacerLocked = new WindowSurfacePlacer(this);
968         mLayersController = new WindowLayersController(this);
969
970         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
971
972         mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG_WM));
973
974         mFxSession = new SurfaceSession();
975         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
976         mDisplays = mDisplayManager.getDisplays();
977         for (Display display : mDisplays) {
978             createDisplayContentLocked(display);
979         }
980
981         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
982
983         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
984         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
985         mPowerManagerInternal.registerLowPowerModeObserver(
986                 new PowerManagerInternal.LowPowerModeListener() {
987             @Override
988             public void onLowPowerModeChanged(boolean enabled) {
989                 synchronized (mWindowMap) {
990                     if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
991                         mAnimationsDisabled = enabled;
992                         dispatchNewAnimatorScaleLocked(null);
993                     }
994                 }
995             }
996         });
997         mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
998         mScreenFrozenLock = mPowerManager.newWakeLock(
999                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
1000         mScreenFrozenLock.setReferenceCounted(false);
1001
1002         mAppTransition = new AppTransition(context, this);
1003         mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
1004
1005         mBoundsAnimationController =
1006                 new BoundsAnimationController(mAppTransition, UiThread.getHandler());
1007
1008         mActivityManager = ActivityManagerNative.getDefault();
1009         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1010         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
1011         AppOpsManager.OnOpChangedInternalListener opListener =
1012                 new AppOpsManager.OnOpChangedInternalListener() {
1013                     @Override public void onOpChanged(int op, String packageName) {
1014                         updateAppOpsState();
1015                     }
1016                 };
1017         mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener);
1018         mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
1019
1020         // Get persisted window scale setting
1021         mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1022                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
1023         mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1024                 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
1025         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
1026                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
1027
1028         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
1029         IntentFilter filter = new IntentFilter();
1030         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1031         mContext.registerReceiver(mBroadcastReceiver, filter);
1032
1033         mSettingsObserver = new SettingsObserver();
1034
1035         mHoldingScreenWakeLock = mPowerManager.newWakeLock(
1036                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
1037         mHoldingScreenWakeLock.setReferenceCounted(false);
1038
1039         mAnimator = new WindowAnimator(this);
1040
1041         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1042                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1043
1044
1045         LocalServices.addService(WindowManagerInternal.class, new LocalService());
1046         initPolicy();
1047
1048         // Add ourself to the Watchdog monitors.
1049         Watchdog.getInstance().addMonitor(this);
1050
1051         SurfaceControl.openTransaction();
1052         try {
1053             createWatermarkInTransaction();
1054         } finally {
1055             SurfaceControl.closeTransaction();
1056         }
1057
1058         showEmulatorDisplayOverlayIfNeeded();
1059     }
1060
1061     public InputMonitor getInputMonitor() {
1062         return mInputMonitor;
1063     }
1064
1065     @Override
1066     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1067             throws RemoteException {
1068         try {
1069             return super.onTransact(code, data, reply, flags);
1070         } catch (RuntimeException e) {
1071             // The window manager only throws security exceptions, so let's
1072             // log all others.
1073             if (!(e instanceof SecurityException)) {
1074                 Slog.wtf(TAG_WM, "Window Manager Crash", e);
1075             }
1076             throw e;
1077         }
1078     }
1079
1080     private void placeWindowAfter(WindowState pos, WindowState window) {
1081         final WindowList windows = pos.getWindowList();
1082         final int i = windows.indexOf(pos);
1083         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1084             TAG_WM, "Adding window " + window + " at "
1085             + (i+1) + " of " + windows.size() + " (after " + pos + ")");
1086         windows.add(i+1, window);
1087         mWindowsChanged = true;
1088     }
1089
1090     private void placeWindowBefore(WindowState pos, WindowState window) {
1091         final WindowList windows = pos.getWindowList();
1092         int i = windows.indexOf(pos);
1093         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1094             TAG_WM, "Adding window " + window + " at "
1095             + i + " of " + windows.size() + " (before " + pos + ")");
1096         if (i < 0) {
1097             Slog.w(TAG_WM, "placeWindowBefore: Unable to find " + pos + " in " + windows);
1098             i = 0;
1099         }
1100         windows.add(i, window);
1101         mWindowsChanged = true;
1102     }
1103
1104     //This method finds out the index of a window that has the same app token as
1105     //win. used for z ordering the windows in mWindows
1106     private int findIdxBasedOnAppTokens(WindowState win) {
1107         WindowList windows = win.getWindowList();
1108         for(int j = windows.size() - 1; j >= 0; j--) {
1109             WindowState wentry = windows.get(j);
1110             if(wentry.mAppToken == win.mAppToken) {
1111                 return j;
1112             }
1113         }
1114         return -1;
1115     }
1116
1117     /**
1118      * Return the list of Windows from the passed token on the given Display.
1119      * @param token The token with all the windows.
1120      * @param displayContent The display we are interested in.
1121      * @return List of windows from token that are on displayContent.
1122      */
1123     private WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
1124         final WindowList windowList = new WindowList();
1125         final int count = token.windows.size();
1126         for (int i = 0; i < count; i++) {
1127             final WindowState win = token.windows.get(i);
1128             if (win.getDisplayContent() == displayContent) {
1129                 windowList.add(win);
1130             }
1131         }
1132         return windowList;
1133     }
1134
1135     /**
1136      * Recursive search through a WindowList and all of its windows' children.
1137      * @param targetWin The window to search for.
1138      * @param windows The list to search.
1139      * @return The index of win in windows or of the window that is an ancestor of win.
1140      */
1141     private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
1142         for (int i = windows.size() - 1; i >= 0; i--) {
1143             final WindowState w = windows.get(i);
1144             if (w == targetWin) {
1145                 return i;
1146             }
1147             if (!w.mChildWindows.isEmpty()) {
1148                 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
1149                     return i;
1150                 }
1151             }
1152         }
1153         return -1;
1154     }
1155
1156     private int addAppWindowToListLocked(final WindowState win) {
1157         final DisplayContent displayContent = win.getDisplayContent();
1158         if (displayContent == null) {
1159             // It doesn't matter this display is going away.
1160             return 0;
1161         }
1162         final IWindow client = win.mClient;
1163         final WindowToken token = win.mToken;
1164
1165         final WindowList windows = displayContent.getWindowList();
1166         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1167         int tokenWindowsPos = 0;
1168         if (!tokenWindowList.isEmpty()) {
1169             return addAppWindowToTokenListLocked(win, token, windows, tokenWindowList);
1170         }
1171
1172         // No windows from this token on this display
1173         if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " + client.asBinder()
1174                 + " (token=" + token + ")");
1175         // Figure out where the window should go, based on the
1176         // order of applications.
1177         WindowState pos = null;
1178
1179         final ArrayList<Task> tasks = displayContent.getTasks();
1180         int taskNdx;
1181         int tokenNdx = -1;
1182         for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1183             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1184             for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
1185                 final AppWindowToken t = tokens.get(tokenNdx);
1186                 if (t == token) {
1187                     --tokenNdx;
1188                     if (tokenNdx < 0) {
1189                         --taskNdx;
1190                         if (taskNdx >= 0) {
1191                             tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
1192                         }
1193                     }
1194                     break;
1195                 }
1196
1197                 // We haven't reached the token yet; if this token
1198                 // is not going to the bottom and has windows on this display, we can
1199                 // use it as an anchor for when we do reach the token.
1200                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1201                 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
1202                     pos = tokenWindowList.get(0);
1203                 }
1204             }
1205             if (tokenNdx >= 0) {
1206                 // early exit
1207                 break;
1208             }
1209         }
1210
1211         // We now know the index into the apps.  If we found
1212         // an app window above, that gives us the position; else
1213         // we need to look some more.
1214         if (pos != null) {
1215             // Move behind any windows attached to this one.
1216             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1217             if (atoken != null) {
1218                 tokenWindowList =
1219                         getTokenWindowsOnDisplay(atoken, displayContent);
1220                 final int NC = tokenWindowList.size();
1221                 if (NC > 0) {
1222                     WindowState bottom = tokenWindowList.get(0);
1223                     if (bottom.mSubLayer < 0) {
1224                         pos = bottom;
1225                     }
1226                 }
1227             }
1228             placeWindowBefore(pos, win);
1229             return tokenWindowsPos;
1230         }
1231
1232         // Continue looking down until we find the first
1233         // token that has windows on this display.
1234         for ( ; taskNdx >= 0; --taskNdx) {
1235             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1236             for ( ; tokenNdx >= 0; --tokenNdx) {
1237                 final AppWindowToken t = tokens.get(tokenNdx);
1238                 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1239                 final int NW = tokenWindowList.size();
1240                 if (NW > 0) {
1241                     pos = tokenWindowList.get(NW-1);
1242                     break;
1243                 }
1244             }
1245             if (tokenNdx >= 0) {
1246                 // found
1247                 break;
1248             }
1249         }
1250
1251         if (pos != null) {
1252             // Move in front of any windows attached to this
1253             // one.
1254             WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1255             if (atoken != null) {
1256                 final int NC = atoken.windows.size();
1257                 if (NC > 0) {
1258                     WindowState top = atoken.windows.get(NC-1);
1259                     if (top.mSubLayer >= 0) {
1260                         pos = top;
1261                     }
1262                 }
1263             }
1264             placeWindowAfter(pos, win);
1265             return tokenWindowsPos;
1266         }
1267
1268         // Just search for the start of this layer.
1269         final int myLayer = win.mBaseLayer;
1270         int i;
1271         for (i = windows.size() - 1; i >= 0; --i) {
1272             WindowState w = windows.get(i);
1273             // Dock divider shares the base layer with application windows, but we want to always
1274             // keep it above the application windows. The sharing of the base layer is intended
1275             // for window animations, which need to be above the dock divider for the duration
1276             // of the animation.
1277             if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
1278                 break;
1279             }
1280         }
1281         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1282                 "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
1283                         + windows.size());
1284         windows.add(i + 1, win);
1285         mWindowsChanged = true;
1286         return tokenWindowsPos;
1287     }
1288
1289     private int addAppWindowToTokenListLocked(WindowState win, WindowToken token,
1290             WindowList windows, WindowList tokenWindowList) {
1291         int tokenWindowsPos;
1292         // If this application has existing windows, we
1293         // simply place the new window on top of them... but
1294         // keep the starting window on top.
1295         if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
1296             // Base windows go behind everything else.
1297             WindowState lowestWindow = tokenWindowList.get(0);
1298             placeWindowBefore(lowestWindow, win);
1299             tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
1300         } else {
1301             AppWindowToken atoken = win.mAppToken;
1302             final int windowListPos = tokenWindowList.size();
1303             WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
1304             if (atoken != null && lastWindow == atoken.startingWindow) {
1305                 placeWindowBefore(lastWindow, win);
1306                 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
1307             } else {
1308                 int newIdx = findIdxBasedOnAppTokens(win);
1309                 //there is a window above this one associated with the same
1310                 //apptoken note that the window could be a floating window
1311                 //that was created later or a window at the top of the list of
1312                 //windows associated with this token.
1313                 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1314                         "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
1315                                 + windows.size());
1316                 windows.add(newIdx + 1, win);
1317                 if (newIdx < 0) {
1318                     // No window from token found on win's display.
1319                     tokenWindowsPos = 0;
1320                 } else {
1321                     tokenWindowsPos = indexOfWinInWindowList(
1322                             windows.get(newIdx), token.windows) + 1;
1323                 }
1324                 mWindowsChanged = true;
1325             }
1326         }
1327         return tokenWindowsPos;
1328     }
1329
1330     private void addFreeWindowToListLocked(final WindowState win) {
1331         final WindowList windows = win.getWindowList();
1332
1333         // Figure out where window should go, based on layer.
1334         final int myLayer = win.mBaseLayer;
1335         int i;
1336         for (i = windows.size() - 1; i >= 0; i--) {
1337             final WindowState otherWin = windows.get(i);
1338             if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= myLayer) {
1339                 // Wallpaper wanders through the window list, for example to position itself
1340                 // directly behind keyguard. Because of this it will break the ordering based on
1341                 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
1342                 // we don't want the new window to appear above them. An example of this is adding
1343                 // of the docked stack divider. Consider a scenario with the following ordering (top
1344                 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
1345                 // to land below the assist preview, so the dock divider must ignore the wallpaper,
1346                 // with which it shares the base layer.
1347                 break;
1348             }
1349         }
1350         i++;
1351         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1352                 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1353         windows.add(i, win);
1354         mWindowsChanged = true;
1355     }
1356
1357     private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1358         final WindowToken token = win.mToken;
1359         final DisplayContent displayContent = win.getDisplayContent();
1360         if (displayContent == null) {
1361             return;
1362         }
1363         final WindowState attached = win.mAttachedWindow;
1364
1365         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1366
1367         // Figure out this window's ordering relative to the window
1368         // it is attached to.
1369         final int NA = tokenWindowList.size();
1370         final int sublayer = win.mSubLayer;
1371         int largestSublayer = Integer.MIN_VALUE;
1372         WindowState windowWithLargestSublayer = null;
1373         int i;
1374         for (i = 0; i < NA; i++) {
1375             WindowState w = tokenWindowList.get(i);
1376             final int wSublayer = w.mSubLayer;
1377             if (wSublayer >= largestSublayer) {
1378                 largestSublayer = wSublayer;
1379                 windowWithLargestSublayer = w;
1380             }
1381             if (sublayer < 0) {
1382                 // For negative sublayers, we go below all windows
1383                 // in the same sublayer.
1384                 if (wSublayer >= sublayer) {
1385                     if (addToToken) {
1386                         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1387                         token.windows.add(i, win);
1388                     }
1389                     placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1390                     break;
1391                 }
1392             } else {
1393                 // For positive sublayers, we go above all windows
1394                 // in the same sublayer.
1395                 if (wSublayer > sublayer) {
1396                     if (addToToken) {
1397                         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1398                         token.windows.add(i, win);
1399                     }
1400                     placeWindowBefore(w, win);
1401                     break;
1402                 }
1403             }
1404         }
1405         if (i >= NA) {
1406             if (addToToken) {
1407                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1408                 token.windows.add(win);
1409             }
1410             if (sublayer < 0) {
1411                 placeWindowBefore(attached, win);
1412             } else {
1413                 placeWindowAfter(largestSublayer >= 0
1414                                  ? windowWithLargestSublayer
1415                                  : attached,
1416                                  win);
1417             }
1418         }
1419     }
1420
1421     private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1422         if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindowToListInOrderLocked: win=" + win +
1423                 " Callers=" + Debug.getCallers(4));
1424         if (win.mAttachedWindow == null) {
1425             final WindowToken token = win.mToken;
1426             int tokenWindowsPos = 0;
1427             if (token.appWindowToken != null) {
1428                 tokenWindowsPos = addAppWindowToListLocked(win);
1429             } else {
1430                 addFreeWindowToListLocked(win);
1431             }
1432             if (addToToken) {
1433                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1434                 token.windows.add(tokenWindowsPos, win);
1435             }
1436         } else {
1437             addAttachedWindowToListLocked(win, addToToken);
1438         }
1439
1440         final AppWindowToken appToken = win.mAppToken;
1441         if (appToken != null) {
1442             if (addToToken) {
1443                 appToken.addWindow(win);
1444             }
1445         }
1446     }
1447
1448     static boolean canBeImeTarget(WindowState w) {
1449         final int fl = w.mAttrs.flags
1450                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1451         final int type = w.mAttrs.type;
1452         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1453                 || type == TYPE_APPLICATION_STARTING) {
1454             if (DEBUG_INPUT_METHOD) {
1455                 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1456                 if (!w.isVisibleOrAdding()) {
1457                     Slog.i(TAG_WM, "  mSurfaceController=" + w.mWinAnimator.mSurfaceController
1458                             + " relayoutCalled=" + w.mRelayoutCalled
1459                             + " viewVis=" + w.mViewVisibility
1460                             + " policyVis=" + w.mPolicyVisibility
1461                             + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1462                             + " attachHid=" + w.mAttachedHidden
1463                             + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
1464                     if (w.mAppToken != null) {
1465                         Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1466                     }
1467                 }
1468             }
1469             return w.isVisibleOrAdding();
1470         }
1471         return false;
1472     }
1473
1474     /**
1475      * Dig through the WindowStates and find the one that the Input Method will target.
1476      * @param willMove
1477      * @return The index+1 in mWindows of the discovered target.
1478      */
1479     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1480         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1481         // same display. Or even when the current IME/target are not on the same screen as the next
1482         // IME/target. For now only look for input windows on the main screen.
1483         WindowList windows = getDefaultWindowListLocked();
1484         WindowState w = null;
1485         int i;
1486         for (i = windows.size() - 1; i >= 0; --i) {
1487             WindowState win = windows.get(i);
1488
1489             if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
1490                     + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1491             if (canBeImeTarget(win)) {
1492                 w = win;
1493                 //Slog.i(TAG_WM, "Putting input method here!");
1494
1495                 // Yet more tricksyness!  If this window is a "starting"
1496                 // window, we do actually want to be on top of it, but
1497                 // it is not -really- where input will go.  So if the caller
1498                 // is not actually looking to move the IME, look down below
1499                 // for a real window to target...
1500                 if (!willMove
1501                         && w.mAttrs.type == TYPE_APPLICATION_STARTING
1502                         && i > 0) {
1503                     WindowState wb = windows.get(i-1);
1504                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1505                         i--;
1506                         w = wb;
1507                     }
1508                 }
1509                 break;
1510             }
1511         }
1512
1513         // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1514
1515         if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
1516
1517         // Now, a special case -- if the last target's window is in the
1518         // process of exiting, and is above the new target, keep on the
1519         // last target to avoid flicker.  Consider for example a Dialog with
1520         // the IME shown: when the Dialog is dismissed, we want to keep
1521         // the IME above it until it is completely gone so it doesn't drop
1522         // behind the dialog or its full-screen scrim.
1523         final WindowState curTarget = mInputMethodTarget;
1524         if (curTarget != null
1525                 && curTarget.isDisplayedLw()
1526                 && curTarget.isClosing()
1527                 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1528             if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
1529             return windows.indexOf(curTarget) + 1;
1530         }
1531
1532         if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
1533                 + w + " willMove=" + willMove);
1534
1535         if (willMove && w != null) {
1536             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1537             if (token != null) {
1538
1539                 // Now some fun for dealing with window animations that
1540                 // modify the Z order.  We need to look at all windows below
1541                 // the current target that are in this app, finding the highest
1542                 // visible one in layering.
1543                 WindowState highestTarget = null;
1544                 int highestPos = 0;
1545                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1546                     WindowList curWindows = curTarget.getWindowList();
1547                     int pos = curWindows.indexOf(curTarget);
1548                     while (pos >= 0) {
1549                         WindowState win = curWindows.get(pos);
1550                         if (win.mAppToken != token) {
1551                             break;
1552                         }
1553                         if (!win.mRemoved) {
1554                             if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1555                                     highestTarget.mWinAnimator.mAnimLayer) {
1556                                 highestTarget = win;
1557                                 highestPos = pos;
1558                             }
1559                         }
1560                         pos--;
1561                     }
1562                 }
1563
1564                 if (highestTarget != null) {
1565                     if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget
1566                             + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1567                             + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1568                             + " new layer=" + w.mWinAnimator.mAnimLayer);
1569
1570                     if (mAppTransition.isTransitionSet()) {
1571                         // If we are currently setting up for an animation,
1572                         // hold everything until we can find out what will happen.
1573                         mInputMethodTargetWaitingAnim = true;
1574                         mInputMethodTarget = highestTarget;
1575                         return highestPos + 1;
1576                     } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1577                             highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1578                         // If the window we are currently targeting is involved
1579                         // with an animation, and it is on top of the next target
1580                         // we will be over, then hold off on moving until
1581                         // that is done.
1582                         mInputMethodTargetWaitingAnim = true;
1583                         mInputMethodTarget = highestTarget;
1584                         return highestPos + 1;
1585                     }
1586                 }
1587             }
1588         }
1589
1590         //Slog.i(TAG_WM, "Placing input method @" + (i+1));
1591         if (w != null) {
1592             if (willMove) {
1593                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1594                         + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1595                 mInputMethodTarget = w;
1596                 mInputMethodTargetWaitingAnim = false;
1597                 if (w.mAppToken != null) {
1598                     mLayersController.setInputMethodAnimLayerAdjustment(
1599                             w.mAppToken.mAppAnimator.animLayerAdjustment);
1600                 } else {
1601                     mLayersController.setInputMethodAnimLayerAdjustment(0);
1602                 }
1603             }
1604
1605             // If the docked divider is visible, we still need to go through this whole
1606             // excercise to find the appropriate input method target (used for animations
1607             // and dialog adjustments), but for purposes of Z ordering we simply wish to
1608             // place it above the docked divider. Unless it is already above the divider.
1609             WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow();
1610             if (dockedDivider != null && dockedDivider.isVisibleLw()) {
1611                 int dividerIndex = windows.indexOf(dockedDivider);
1612                 if (dividerIndex > 0 && dividerIndex > i) {
1613                     return dividerIndex + 1;
1614                 }
1615             }
1616             return i+1;
1617         }
1618         if (willMove) {
1619             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to null."
1620                     + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1621             mInputMethodTarget = null;
1622             mLayersController.setInputMethodAnimLayerAdjustment(0);
1623         }
1624         return -1;
1625     }
1626
1627     void addInputMethodWindowToListLocked(WindowState win) {
1628         int pos = findDesiredInputMethodWindowIndexLocked(true);
1629         if (pos >= 0) {
1630             win.mTargetAppToken = mInputMethodTarget.mAppToken;
1631             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1632                     TAG_WM, "Adding input method window " + win + " at " + pos);
1633             // TODO(multidisplay): IMEs are only supported on the default display.
1634             getDefaultWindowListLocked().add(pos, win);
1635             mWindowsChanged = true;
1636             moveInputMethodDialogsLocked(pos + 1);
1637             return;
1638         }
1639         win.mTargetAppToken = null;
1640         addWindowToListInOrderLocked(win, true);
1641         moveInputMethodDialogsLocked(pos);
1642     }
1643
1644     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1645         WindowList windows = win.getWindowList();
1646         int wpos = windows.indexOf(win);
1647         if (wpos >= 0) {
1648             if (wpos < interestingPos) interestingPos--;
1649             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + win);
1650             windows.remove(wpos);
1651             mWindowsChanged = true;
1652             int NC = win.mChildWindows.size();
1653             while (NC > 0) {
1654                 NC--;
1655                 WindowState cw = win.mChildWindows.get(NC);
1656                 int cpos = windows.indexOf(cw);
1657                 if (cpos >= 0) {
1658                     if (cpos < interestingPos) interestingPos--;
1659                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing child at "
1660                             + cpos + ": " + cw);
1661                     windows.remove(cpos);
1662                 }
1663             }
1664         }
1665         return interestingPos;
1666     }
1667
1668     private void reAddWindowToListInOrderLocked(WindowState win) {
1669         addWindowToListInOrderLocked(win, false);
1670         // This is a hack to get all of the child windows added as well
1671         // at the right position.  Child windows should be rare and
1672         // this case should be rare, so it shouldn't be that big a deal.
1673         WindowList windows = win.getWindowList();
1674         int wpos = windows.indexOf(win);
1675         if (wpos >= 0) {
1676             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
1677             windows.remove(wpos);
1678             mWindowsChanged = true;
1679             reAddWindowLocked(wpos, win);
1680         }
1681     }
1682
1683     void logWindowList(final WindowList windows, String prefix) {
1684         int N = windows.size();
1685         while (N > 0) {
1686             N--;
1687             Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
1688         }
1689     }
1690
1691     void moveInputMethodDialogsLocked(int pos) {
1692         ArrayList<WindowState> dialogs = mInputMethodDialogs;
1693
1694         // TODO(multidisplay): IMEs are only supported on the default display.
1695         WindowList windows = getDefaultWindowListLocked();
1696         final int N = dialogs.size();
1697         if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
1698         for (int i=0; i<N; i++) {
1699             pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1700         }
1701         if (DEBUG_INPUT_METHOD) {
1702             Slog.v(TAG_WM, "Window list w/pos=" + pos);
1703             logWindowList(windows, "  ");
1704         }
1705
1706         if (pos >= 0) {
1707             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1708             // Skip windows owned by the input method.
1709             if (mInputMethodWindow != null) {
1710                 while (pos < windows.size()) {
1711                     WindowState wp = windows.get(pos);
1712                     if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) {
1713                         pos++;
1714                         continue;
1715                     }
1716                     break;
1717                 }
1718             }
1719             if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
1720             for (int i=0; i<N; i++) {
1721                 WindowState win = dialogs.get(i);
1722                 win.mTargetAppToken = targetAppToken;
1723                 pos = reAddWindowLocked(pos, win);
1724             }
1725             if (DEBUG_INPUT_METHOD) {
1726                 Slog.v(TAG_WM, "Final window list:");
1727                 logWindowList(windows, "  ");
1728             }
1729             return;
1730         }
1731         for (int i=0; i<N; i++) {
1732             WindowState win = dialogs.get(i);
1733             win.mTargetAppToken = null;
1734             reAddWindowToListInOrderLocked(win);
1735             if (DEBUG_INPUT_METHOD) {
1736                 Slog.v(TAG_WM, "No IM target, final list:");
1737                 logWindowList(windows, "  ");
1738             }
1739         }
1740     }
1741
1742     boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1743         final WindowState imWin = mInputMethodWindow;
1744         final int DN = mInputMethodDialogs.size();
1745         if (imWin == null && DN == 0) {
1746             return false;
1747         }
1748
1749         // TODO(multidisplay): IMEs are only supported on the default display.
1750         WindowList windows = getDefaultWindowListLocked();
1751
1752         int imPos = findDesiredInputMethodWindowIndexLocked(true);
1753         if (imPos >= 0) {
1754             // In this case, the input method windows are to be placed
1755             // immediately above the window they are targeting.
1756
1757             // First check to see if the input method windows are already
1758             // located here, and contiguous.
1759             final int N = windows.size();
1760             WindowState firstImWin = imPos < N
1761                     ? windows.get(imPos) : null;
1762
1763             // Figure out the actual input method window that should be
1764             // at the bottom of their stack.
1765             WindowState baseImWin = imWin != null
1766                     ? imWin : mInputMethodDialogs.get(0);
1767             if (baseImWin.mChildWindows.size() > 0) {
1768                 WindowState cw = baseImWin.mChildWindows.get(0);
1769                 if (cw.mSubLayer < 0) baseImWin = cw;
1770             }
1771
1772             if (firstImWin == baseImWin) {
1773                 // The windows haven't moved...  but are they still contiguous?
1774                 // First find the top IM window.
1775                 int pos = imPos+1;
1776                 while (pos < N) {
1777                     if (!(windows.get(pos)).mIsImWindow) {
1778                         break;
1779                     }
1780                     pos++;
1781                 }
1782                 pos++;
1783                 // Now there should be no more input method windows above.
1784                 while (pos < N) {
1785                     if ((windows.get(pos)).mIsImWindow) {
1786                         break;
1787                     }
1788                     pos++;
1789                 }
1790                 if (pos >= N) {
1791                     // Z order is good.
1792                     // The IM target window may be changed, so update the mTargetAppToken.
1793                     if (imWin != null) {
1794                         imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1795                     }
1796                     return false;
1797                 }
1798             }
1799
1800             if (imWin != null) {
1801                 if (DEBUG_INPUT_METHOD) {
1802                     Slog.v(TAG_WM, "Moving IM from " + imPos);
1803                     logWindowList(windows, "  ");
1804                 }
1805                 imPos = tmpRemoveWindowLocked(imPos, imWin);
1806                 if (DEBUG_INPUT_METHOD) {
1807                     Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
1808                     logWindowList(windows, "  ");
1809                 }
1810                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1811                 reAddWindowLocked(imPos, imWin);
1812                 if (DEBUG_INPUT_METHOD) {
1813                     Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
1814                     logWindowList(windows, "  ");
1815                 }
1816                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1817             } else {
1818                 moveInputMethodDialogsLocked(imPos);
1819             }
1820
1821         } else {
1822             // In this case, the input method windows go in a fixed layer,
1823             // because they aren't currently associated with a focus window.
1824
1825             if (imWin != null) {
1826                 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
1827                 tmpRemoveWindowLocked(0, imWin);
1828                 imWin.mTargetAppToken = null;
1829                 reAddWindowToListInOrderLocked(imWin);
1830                 if (DEBUG_INPUT_METHOD) {
1831                     Slog.v(TAG_WM, "List with no IM target:");
1832                     logWindowList(windows, "  ");
1833                 }
1834                 if (DN > 0) moveInputMethodDialogsLocked(-1);
1835             } else {
1836                 moveInputMethodDialogsLocked(-1);
1837             }
1838
1839         }
1840
1841         if (needAssignLayers) {
1842             mLayersController.assignLayersLocked(windows);
1843         }
1844
1845         return true;
1846     }
1847
1848     private static boolean excludeWindowTypeFromTapOutTask(int windowType) {
1849         switch (windowType) {
1850             case TYPE_STATUS_BAR:
1851             case TYPE_NAVIGATION_BAR:
1852             case TYPE_INPUT_METHOD_DIALOG:
1853                 return true;
1854         }
1855         return false;
1856     }
1857
1858     public int addWindow(Session session, IWindow client, int seq,
1859             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
1860             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
1861             InputChannel outInputChannel) {
1862         int[] appOp = new int[1];
1863         int res = mPolicy.checkAddPermission(attrs, appOp);
1864         if (res != WindowManagerGlobal.ADD_OKAY) {
1865             return res;
1866         }
1867
1868         boolean reportNewConfig = false;
1869         WindowState attachedWindow = null;
1870         long origId;
1871         final int type = attrs.type;
1872
1873         synchronized(mWindowMap) {
1874             if (!mDisplayReady) {
1875                 throw new IllegalStateException("Display has not been initialialized");
1876             }
1877
1878             final DisplayContent displayContent = getDisplayContentLocked(displayId);
1879             if (displayContent == null) {
1880                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
1881                         + displayId + ".  Aborting.");
1882                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1883             }
1884             if (!displayContent.hasAccess(session.mUid)) {
1885                 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
1886                         + "does not have access: " + displayId + ".  Aborting.");
1887                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1888             }
1889
1890             if (mWindowMap.containsKey(client.asBinder())) {
1891                 Slog.w(TAG_WM, "Window " + client + " is already added");
1892                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1893             }
1894
1895             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1896                 attachedWindow = windowForClientLocked(null, attrs.token, false);
1897                 if (attachedWindow == null) {
1898                     Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
1899                           + attrs.token + ".  Aborting.");
1900                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1901                 }
1902                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1903                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1904                     Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
1905                             + attrs.token + ".  Aborting.");
1906                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1907                 }
1908             }
1909
1910             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
1911                 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display.  Aborting.");
1912                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1913             }
1914
1915             boolean addToken = false;
1916             WindowToken token = mTokenMap.get(attrs.token);
1917             AppWindowToken atoken = null;
1918             if (token == null) {
1919                 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1920                     Slog.w(TAG_WM, "Attempted to add application window with unknown token "
1921                           + attrs.token + ".  Aborting.");
1922                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1923                 }
1924                 if (type == TYPE_INPUT_METHOD) {
1925                     Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
1926                           + attrs.token + ".  Aborting.");
1927                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1928                 }
1929                 if (type == TYPE_VOICE_INTERACTION) {
1930                     Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
1931                           + attrs.token + ".  Aborting.");
1932                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1933                 }
1934                 if (type == TYPE_WALLPAPER) {
1935                     Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
1936                           + attrs.token + ".  Aborting.");
1937                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1938                 }
1939                 if (type == TYPE_DREAM) {
1940                     Slog.w(TAG_WM, "Attempted to add Dream window with unknown token "
1941                           + attrs.token + ".  Aborting.");
1942                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1943                 }
1944                 if (type == TYPE_QS_DIALOG) {
1945                     Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token "
1946                           + attrs.token + ".  Aborting.");
1947                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1948                 }
1949                 if (type == TYPE_ACCESSIBILITY_OVERLAY) {
1950                     Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token "
1951                             + attrs.token + ".  Aborting.");
1952                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1953                 }
1954                 token = new WindowToken(this, attrs.token, -1, false);
1955                 addToken = true;
1956             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1957                 atoken = token.appWindowToken;
1958                 if (atoken == null) {
1959                     Slog.w(TAG_WM, "Attempted to add window with non-application token "
1960                           + token + ".  Aborting.");
1961                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
1962                 } else if (atoken.removed) {
1963                     Slog.w(TAG_WM, "Attempted to add window with exiting application token "
1964                           + token + ".  Aborting.");
1965                     return WindowManagerGlobal.ADD_APP_EXITING;
1966                 }
1967                 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1968                     // No need for this guy!
1969                     if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v(
1970                             TAG_WM, "**** NO NEED TO START: " + attrs.getTitle());
1971                     return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
1972                 }
1973             } else if (type == TYPE_INPUT_METHOD) {
1974                 if (token.windowType != TYPE_INPUT_METHOD) {
1975                     Slog.w(TAG_WM, "Attempted to add input method window with bad token "
1976                             + attrs.token + ".  Aborting.");
1977                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1978                 }
1979             } else if (type == TYPE_VOICE_INTERACTION) {
1980                 if (token.windowType != TYPE_VOICE_INTERACTION) {
1981                     Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token "
1982                             + attrs.token + ".  Aborting.");
1983                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1984                 }
1985             } else if (type == TYPE_WALLPAPER) {
1986                 if (token.windowType != TYPE_WALLPAPER) {
1987                     Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token "
1988                             + attrs.token + ".  Aborting.");
1989                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1990                 }
1991             } else if (type == TYPE_DREAM) {
1992                 if (token.windowType != TYPE_DREAM) {
1993                     Slog.w(TAG_WM, "Attempted to add Dream window with bad token "
1994                             + attrs.token + ".  Aborting.");
1995                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1996                 }
1997             } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
1998                 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1999                     Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token "
2000                             + attrs.token + ".  Aborting.");
2001                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2002                 }
2003             } else if (type == TYPE_QS_DIALOG) {
2004                 if (token.windowType != TYPE_QS_DIALOG) {
2005                     Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
2006                             + attrs.token + ".  Aborting.");
2007                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2008                 }
2009             } else if (token.appWindowToken != null) {
2010                 Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type);
2011                 // It is not valid to use an app token with other system types; we will
2012                 // instead make a new token for it (as if null had been passed in for the token).
2013                 attrs.token = null;
2014                 token = new WindowToken(this, null, -1, false);
2015                 addToken = true;
2016             }
2017
2018             WindowState win = new WindowState(this, session, client, token,
2019                     attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2020             if (win.mDeathRecipient == null) {
2021                 // Client has apparently died, so there is no reason to
2022                 // continue.
2023                 Slog.w(TAG_WM, "Adding window client " + client.asBinder()
2024                         + " that is dead, aborting.");
2025                 return WindowManagerGlobal.ADD_APP_EXITING;
2026             }
2027
2028             if (win.getDisplayContent() == null) {
2029                 Slog.w(TAG_WM, "Adding window to Display that has been removed.");
2030                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2031             }
2032
2033             mPolicy.adjustWindowParamsLw(win.mAttrs);
2034             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2035
2036             res = mPolicy.prepareAddWindowLw(win, attrs);
2037             if (res != WindowManagerGlobal.ADD_OKAY) {
2038                 return res;
2039             }
2040
2041             final boolean openInputChannels = (outInputChannel != null
2042                     && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
2043             if  (openInputChannels) {
2044                 win.openInputChannel(outInputChannel);
2045             }
2046
2047             // From now on, no exceptions or errors allowed!
2048
2049             res = WindowManagerGlobal.ADD_OKAY;
2050
2051             if (excludeWindowTypeFromTapOutTask(type)) {
2052                 displayContent.mTapExcludedWindows.add(win);
2053             }
2054
2055             origId = Binder.clearCallingIdentity();
2056
2057             if (addToken) {
2058                 mTokenMap.put(attrs.token, token);
2059             }
2060             win.attach();
2061             mWindowMap.put(client.asBinder(), win);
2062             if (win.mAppOp != AppOpsManager.OP_NONE) {
2063                 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
2064                         win.getOwningPackage());
2065                 if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
2066                         (startOpResult != AppOpsManager.MODE_DEFAULT)) {
2067                     win.setAppOpVisibilityLw(false);
2068                 }
2069             }
2070
2071             if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2072                 token.appWindowToken.startingWindow = win;
2073                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + token.appWindowToken
2074                         + " startingWindow=" + win);
2075             }
2076
2077             boolean imMayMove = true;
2078
2079             if (type == TYPE_INPUT_METHOD) {
2080                 win.mGivenInsetsPending = true;
2081                 mInputMethodWindow = win;
2082                 addInputMethodWindowToListLocked(win);
2083                 imMayMove = false;
2084             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2085                 mInputMethodDialogs.add(win);
2086                 addWindowToListInOrderLocked(win, true);
2087                 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2088                 imMayMove = false;
2089             } else {
2090                 addWindowToListInOrderLocked(win, true);
2091                 if (type == TYPE_WALLPAPER) {
2092                     mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
2093                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2094                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2095                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2096                 } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) {
2097                     // If there is currently a wallpaper being shown, and
2098                     // the base layer of the new window is below the current
2099                     // layer of the target window, then adjust the wallpaper.
2100                     // This is to avoid a new window being placed between the
2101                     // wallpaper and its target.
2102                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2103                 }
2104             }
2105
2106             // If the window is being added to a task that's docked but non-resizeable,
2107             // we need to update this new window's scroll position when it's added.
2108             win.applyScrollIfNeeded();
2109
2110             // If the window is being added to a stack that's currently adjusted for IME,
2111             // make sure to apply the same adjust to this new window.
2112             win.applyAdjustForImeIfNeeded();
2113
2114             if (type == TYPE_DOCK_DIVIDER) {
2115                 getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win);
2116             }
2117
2118             final WindowStateAnimator winAnimator = win.mWinAnimator;
2119             winAnimator.mEnterAnimationPending = true;
2120             winAnimator.mEnteringAnimation = true;
2121             // Check if we need to prepare a transition for replacing window first.
2122             if (atoken != null && !prepareWindowReplacementTransition(atoken)) {
2123                 // If not, check if need to set up a dummy transition during display freeze
2124                 // so that the unfreeze wait for the apps to draw. This might be needed if
2125                 // the app is relaunching.
2126                 prepareNoneTransitionForRelaunching(atoken);
2127             }
2128
2129             if (displayContent.isDefaultDisplay) {
2130                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2131                 final Rect taskBounds;
2132                 if (atoken != null && atoken.mTask != null) {
2133                     taskBounds = mTmpRect;
2134                     atoken.mTask.getBounds(mTmpRect);
2135                 } else {
2136                     taskBounds = null;
2137                 }
2138                 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, mRotation,
2139                         displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets,
2140                         outStableInsets, outOutsets)) {
2141                     res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
2142                 }
2143             } else {
2144                 outContentInsets.setEmpty();
2145                 outStableInsets.setEmpty();
2146             }
2147
2148             if (mInTouchMode) {
2149                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2150             }
2151             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2152                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2153             }
2154
2155             mInputMonitor.setUpdateInputWindowsNeededLw();
2156
2157             boolean focusChanged = false;
2158             if (win.canReceiveKeys()) {
2159                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2160                         false /*updateInputWindows*/);
2161                 if (focusChanged) {
2162                     imMayMove = false;
2163                 }
2164             }
2165
2166             if (imMayMove) {
2167                 moveInputMethodWindowsIfNeededLocked(false);
2168             }
2169
2170             mLayersController.assignLayersLocked(displayContent.getWindowList());
2171             // Don't do layout here, the window must call
2172             // relayout to be displayed, so we'll do it there.
2173
2174             if (focusChanged) {
2175                 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
2176             }
2177             mInputMonitor.updateInputWindowsLw(false /*force*/);
2178
2179             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
2180                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
2181
2182             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2183                 reportNewConfig = true;
2184             }
2185             if (attrs.removeTimeoutMilliseconds > 0) {
2186                 mH.sendMessageDelayed(
2187                         mH.obtainMessage(H.WINDOW_REMOVE_TIMEOUT, win),
2188                         attrs.removeTimeoutMilliseconds);
2189             }
2190         }
2191
2192         if (reportNewConfig) {
2193             sendNewConfiguration();
2194         }
2195
2196         Binder.restoreCallingIdentity(origId);
2197
2198         return res;
2199     }
2200
2201     /**
2202      * Returns true if we're done setting up any transitions.
2203      */
2204     private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
2205         atoken.clearAllDrawn();
2206         WindowState replacedWindow = null;
2207         for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
2208             WindowState candidate = atoken.windows.get(i);
2209             if (candidate.mAnimatingExit && candidate.mWillReplaceWindow
2210                     && candidate.mAnimateReplacingWindow) {
2211                 replacedWindow = candidate;
2212             }
2213         }
2214         if (replacedWindow == null) {
2215             // We expect to already receive a request to remove the old window. If it did not
2216             // happen, let's just simply add a window.
2217             return false;
2218         }
2219         // We use the visible frame, because we want the animation to morph the window from what
2220         // was visible to the user to the final destination of the new window.
2221         Rect frame = replacedWindow.mVisibleFrame;
2222         // We treat this as if this activity was opening, so we can trigger the app transition
2223         // animation and piggy-back on existing transition animation infrastructure.
2224         mOpeningApps.add(atoken);
2225         prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
2226         mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
2227                 frame.width(), frame.height());
2228         executeAppTransition();
2229         return true;
2230     }
2231
2232     private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
2233         // Set up a none-transition and add the app to opening apps, so that the display
2234         // unfreeze wait for the apps to be drawn.
2235         // Note that if the display unfroze already because app unfreeze timed out,
2236         // we don't set up the transition anymore and just let it go.
2237         if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
2238             mOpeningApps.add(atoken);
2239             prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
2240             executeAppTransition();
2241         }
2242     }
2243
2244     /**
2245      * Returns whether screen capture is disabled for all windows of a specific user.
2246      */
2247     boolean isScreenCaptureDisabledLocked(int userId) {
2248         Boolean disabled = mScreenCaptureDisabled.get(userId);
2249         if (disabled == null) {
2250             return false;
2251         }
2252         return disabled;
2253     }
2254
2255     boolean isSecureLocked(WindowState w) {
2256         if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
2257             return true;
2258         }
2259         if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
2260             return true;
2261         }
2262         return false;
2263     }
2264
2265     /**
2266      * Set mScreenCaptureDisabled for specific user
2267      */
2268     @Override
2269     public void setScreenCaptureDisabled(int userId, boolean disabled) {
2270         int callingUid = Binder.getCallingUid();
2271         if (callingUid != Process.SYSTEM_UID) {
2272             throw new SecurityException("Only system can call setScreenCaptureDisabled.");
2273         }
2274
2275         synchronized(mWindowMap) {
2276             mScreenCaptureDisabled.put(userId, disabled);
2277             // Update secure surface for all windows belonging to this user.
2278             for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
2279                 WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2280                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
2281                     final WindowState win = windows.get(winNdx);
2282                     if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
2283                         win.mWinAnimator.setSecureLocked(disabled);
2284                     }
2285                 }
2286             }
2287         }
2288     }
2289
2290     private void setupWindowForRemoveOnExit(WindowState win) {
2291         win.mRemoveOnExit = true;
2292         win.setDisplayLayoutNeeded();
2293         // Request a focus update as this window's input channel is already gone. Otherwise
2294         // we could have no focused window in input manager.
2295         final boolean focusChanged = updateFocusedWindowLocked(
2296                 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
2297         mWindowPlacerLocked.performSurfacePlacement();
2298         if (focusChanged) {
2299             mInputMonitor.updateInputWindowsLw(false /*force*/);
2300         }
2301     }
2302
2303     public void removeWindow(Session session, IWindow client) {
2304         synchronized(mWindowMap) {
2305             WindowState win = windowForClientLocked(session, client, false);
2306             if (win == null) {
2307                 return;
2308             }
2309             removeWindowLocked(win);
2310         }
2311     }
2312
2313     void removeWindowLocked(WindowState win) {
2314         removeWindowLocked(win, false);
2315     }
2316
2317     void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) {
2318         win.mWindowRemovalAllowed = true;
2319         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
2320                 "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4));
2321
2322         final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING;
2323         if (startingWindow) {
2324             if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win);
2325         }
2326
2327         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v(
2328                 TAG_WM, "Remove " + win + " client="
2329                 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2330                 + ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers="
2331                 + Debug.getCallers(4));
2332
2333         final long origId = Binder.clearCallingIdentity();
2334
2335         win.disposeInputChannel();
2336
2337         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
2338                 "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController
2339                 + " mAnimatingExit=" + win.mAnimatingExit
2340                 + " mRemoveOnExit=" + win.mRemoveOnExit
2341                 + " mHasSurface=" + win.mHasSurface
2342                 + " surfaceShowing=" + win.mWinAnimator.getShown()
2343                 + " isAnimationSet=" + win.mWinAnimator.isAnimationSet()
2344                 + " app-animation="
2345                 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2346                 + " mWillReplaceWindow=" + win.mWillReplaceWindow
2347                 + " inPendingTransaction="
2348                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2349                 + " mDisplayFrozen=" + mDisplayFrozen
2350                 + " callers=" + Debug.getCallers(6));
2351         // Visibility of the removed window. Will be used later to update orientation later on.
2352         boolean wasVisible = false;
2353         // First, see if we need to run an animation. If we do, we have to hold off on removing the
2354         // window until the animation is done. If the display is frozen, just remove immediately,
2355         // since the animation wouldn't be seen.
2356         if (win.mHasSurface && okToDisplay()) {
2357             final AppWindowToken appToken = win.mAppToken;
2358             if (win.mWillReplaceWindow) {
2359                 // This window is going to be replaced. We need to keep it around until the new one
2360                 // gets added, then we will get rid of this one.
2361                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
2362                         + "added");
2363                 // TODO: We are overloading mAnimatingExit flag to prevent the window state from
2364                 // been removed. We probably need another flag to indicate that window removal
2365                 // should be deffered vs. overloading the flag that says we are playing an exit
2366                 // animation.
2367                 win.mAnimatingExit = true;
2368                 win.mReplacingRemoveRequested = true;
2369                 Binder.restoreCallingIdentity(origId);
2370                 return;
2371             }
2372
2373             if (win.isAnimatingWithSavedSurface() && !appToken.allDrawnExcludingSaved) {
2374                 // We started enter animation early with a saved surface, now the app asks to remove
2375                 // this window. If we remove it now and the app is not yet drawn, we'll show a
2376                 // flicker. Delay the removal now until it's really drawn.
2377                 if (DEBUG_ADD_REMOVE) {
2378                     Slog.d(TAG_WM, "removeWindowLocked: delay removal of " + win
2379                             + " due to early animation");
2380                 }
2381                 // Do not set mAnimatingExit to true here, it will cause the surface to be hidden
2382                 // immediately after the enter animation is done. If the app is not yet drawn then
2383                 // it will show up as a flicker.
2384                 setupWindowForRemoveOnExit(win);
2385                 Binder.restoreCallingIdentity(origId);
2386                 return;
2387             }
2388             // If we are not currently running the exit animation, we need to see about starting one
2389             wasVisible = win.isWinVisibleLw();
2390
2391             if (keepVisibleDeadWindow) {
2392                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2393                         "Not removing " + win + " because app died while it's visible");
2394
2395                 win.mAppDied = true;
2396                 win.setDisplayLayoutNeeded();
2397                 mWindowPlacerLocked.performSurfacePlacement();
2398
2399                 // Set up a replacement input channel since the app is now dead.
2400                 // We need to catch tapping on the dead window to restart the app.
2401                 win.openInputChannel(null);
2402                 mInputMonitor.updateInputWindowsLw(true /*force*/);
2403
2404                 Binder.restoreCallingIdentity(origId);
2405                 return;
2406             }
2407
2408             final WindowStateAnimator winAnimator = win.mWinAnimator;
2409             if (wasVisible) {
2410                 final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
2411
2412                 // Try starting an animation.
2413                 if (winAnimator.applyAnimationLocked(transit, false)) {
2414                     win.mAnimatingExit = true;
2415                 }
2416                 //TODO (multidisplay): Magnification is supported only for the default display.
2417                 if (mAccessibilityController != null
2418                         && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2419                     mAccessibilityController.onWindowTransitionLocked(win, transit);
2420                 }
2421             }
2422             final boolean isAnimating =
2423                     winAnimator.isAnimationSet() && !winAnimator.isDummyAnimation();
2424             final boolean lastWindowIsStartingWindow = startingWindow && appToken != null
2425                     && appToken.allAppWindows.size() == 1;
2426             // We delay the removal of a window if it has a showing surface that can be used to run
2427             // exit animation and it is marked as exiting.
2428             // Also, If isn't the an animating starting window that is the last window in the app.
2429             // We allow the removal of the non-animating starting window now as there is no
2430             // additional window or animation that will trigger its removal.
2431             if (winAnimator.getShown() && win.mAnimatingExit
2432                     && (!lastWindowIsStartingWindow || isAnimating)) {
2433                 // The exit animation is running or should run... wait for it!
2434                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2435                         "Not removing " + win + " due to exit animation ");
2436                 setupWindowForRemoveOnExit(win);
2437                 if (appToken != null) {
2438                     appToken.updateReportedVisibilityLocked();
2439                 }
2440                 Binder.restoreCallingIdentity(origId);
2441                 return;
2442             }
2443         }
2444
2445         removeWindowInnerLocked(win);
2446         // Removing a visible window will effect the computed orientation
2447         // So just update orientation if needed.
2448         if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2449             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2450         }
2451         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2452         Binder.restoreCallingIdentity(origId);
2453     }
2454
2455     void removeWindowInnerLocked(WindowState win) {
2456         if (win.mRemoved) {
2457             // Nothing to do.
2458             if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2459                     "removeWindowInnerLocked: " + win + " Already removed...");
2460             return;
2461         }
2462
2463         for (int i = win.mChildWindows.size() - 1; i >= 0; i--) {
2464             WindowState cwin = win.mChildWindows.get(i);
2465             Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " + win);
2466             removeWindowInnerLocked(cwin);
2467         }
2468
2469         win.mRemoved = true;
2470
2471         if (mInputMethodTarget == win) {
2472             moveInputMethodWindowsIfNeededLocked(false);
2473         }
2474
2475         if (false) {
2476             RuntimeException e = new RuntimeException("here");
2477             e.fillInStackTrace();
2478             Slog.w(TAG_WM, "Removing window " + win, e);
2479         }
2480
2481         final int type = win.mAttrs.type;
2482         if (excludeWindowTypeFromTapOutTask(type)) {
2483             final DisplayContent displaycontent = win.getDisplayContent();
2484             displaycontent.mTapExcludedWindows.remove(win);
2485         }
2486         mPolicy.removeWindowLw(win);
2487         win.removeLocked();
2488
2489         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "removeWindowInnerLocked: " + win);
2490         mWindowMap.remove(win.mClient.asBinder());
2491         if (win.mAppOp != AppOpsManager.OP_NONE) {
2492             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2493         }
2494
2495         mPendingRemove.remove(win);
2496         mResizingWindows.remove(win);
2497         mWindowsChanged = true;
2498         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
2499
2500         if (mInputMethodWindow == win) {
2501             mInputMethodWindow = null;
2502         } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2503             mInputMethodDialogs.remove(win);
2504         }
2505
2506         final WindowToken token = win.mToken;
2507         final AppWindowToken atoken = win.mAppToken;
2508         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
2509         token.windows.remove(win);
2510         if (atoken != null) {
2511             atoken.allAppWindows.remove(win);
2512         }
2513         if (localLOGV) Slog.v(
2514                 TAG_WM, "**** Removing window " + win + ": count="
2515                 + token.windows.size());
2516         if (token.windows.size() == 0) {
2517             if (!token.explicit) {
2518                 mTokenMap.remove(token.token);
2519             } else if (atoken != null) {
2520                 atoken.firstWindowDrawn = false;
2521                 atoken.clearAllDrawn();
2522             }
2523         }
2524
2525         if (atoken != null) {
2526             if (atoken.startingWindow == win) {
2527                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
2528                 scheduleRemoveStartingWindowLocked(atoken);
2529             } else
2530             if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2531                 // If this is the last window and we had requested a starting
2532                 // transition window, well there is no point now.
2533                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
2534                 atoken.startingData = null;
2535             } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2536                 // If this is the last window except for a starting transition
2537                 // window, we need to get rid of the starting transition.
2538                 scheduleRemoveStartingWindowLocked(atoken);
2539             }
2540         }
2541
2542         if (type == TYPE_WALLPAPER) {
2543             mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
2544             getDefaultDisplayContentLocked().pendingLayoutChanges |=
2545                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2546         } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2547             getDefaultDisplayContentLocked().pendingLayoutChanges |=
2548                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2549         }
2550
2551         final WindowList windows = win.getWindowList();
2552         if (windows != null) {
2553             windows.remove(win);
2554             if (!mWindowPlacerLocked.isInLayout()) {
2555                 mLayersController.assignLayersLocked(windows);
2556                 win.setDisplayLayoutNeeded();
2557                 mWindowPlacerLocked.performSurfacePlacement();
2558                 if (win.mAppToken != null) {
2559                     win.mAppToken.updateReportedVisibilityLocked();
2560                 }
2561             }
2562         }
2563
2564         mInputMonitor.updateInputWindowsLw(true /*force*/);
2565     }
2566
2567     public void updateAppOpsState() {
2568         synchronized(mWindowMap) {
2569             final int numDisplays = mDisplayContents.size();
2570             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2571                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2572                 final int numWindows = windows.size();
2573                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2574                     final WindowState win = windows.get(winNdx);
2575                     if (win.mAppOp != AppOpsManager.OP_NONE) {
2576                         final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2577                                 win.getOwningPackage());
2578                         win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
2579                                 mode == AppOpsManager.MODE_DEFAULT);
2580                     }
2581                 }
2582             }
2583         }
2584     }
2585
2586     static void logSurface(WindowState w, String msg, boolean withStackTrace) {
2587         String str = "  SURFACE " + msg + ": " + w;
2588         if (withStackTrace) {
2589             logWithStack(TAG, str);
2590         } else {
2591             Slog.i(TAG_WM, str);
2592         }
2593     }
2594
2595     static void logSurface(SurfaceControl s, String title, String msg) {
2596         String str = "  SURFACE " + s + ": " + msg + " / " + title;
2597         Slog.i(TAG_WM, str);
2598     }
2599
2600     static void logWithStack(String tag, String s) {
2601         RuntimeException e = null;
2602         if (SHOW_STACK_CRAWLS) {
2603             e = new RuntimeException();
2604             e.fillInStackTrace();
2605         }
2606         Slog.i(tag, s, e);
2607     }
2608
2609     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2610         long origId = Binder.clearCallingIdentity();
2611         try {
2612             synchronized (mWindowMap) {
2613                 WindowState w = windowForClientLocked(session, client, false);
2614                 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
2615                         "transparentRegionHint=" + region, false);
2616
2617                 if ((w != null) && w.mHasSurface) {
2618                     w.mWinAnimator.setTransparentRegionHintLocked(region);
2619                 }
2620             }
2621         } finally {
2622             Binder.restoreCallingIdentity(origId);
2623         }
2624     }
2625
2626     void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
2627             Rect visibleInsets, Region touchableRegion) {
2628         long origId = Binder.clearCallingIdentity();
2629         try {
2630             synchronized (mWindowMap) {
2631                 WindowState w = windowForClientLocked(session, client, false);
2632                 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
2633                         + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
2634                         + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
2635                         + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
2636                         + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
2637                 if (w != null) {
2638                     w.mGivenInsetsPending = false;
2639                     w.mGivenContentInsets.set(contentInsets);
2640                     w.mGivenVisibleInsets.set(visibleInsets);
2641                     w.mGivenTouchableRegion.set(touchableRegion);
2642                     w.mTouchableInsets = touchableInsets;
2643                     if (w.mGlobalScale != 1) {
2644                         w.mGivenContentInsets.scale(w.mGlobalScale);
2645                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
2646                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
2647                     }
2648                     w.setDisplayLayoutNeeded();
2649                     mWindowPlacerLocked.performSurfacePlacement();
2650                 }
2651             }
2652         } finally {
2653             Binder.restoreCallingIdentity(origId);
2654         }
2655     }
2656
2657     public void getWindowDisplayFrame(Session session, IWindow client,
2658             Rect outDisplayFrame) {
2659         synchronized(mWindowMap) {
2660             WindowState win = windowForClientLocked(session, client, false);
2661             if (win == null) {
2662                 outDisplayFrame.setEmpty();
2663                 return;
2664             }
2665             outDisplayFrame.set(win.mDisplayFrame);
2666         }
2667     }
2668
2669     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
2670         synchronized (mWindowMap) {
2671             if (mAccessibilityController != null) {
2672                 WindowState window = mWindowMap.get(token);
2673                 //TODO (multidisplay): Magnification is supported only for the default display.
2674                 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2675                     mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
2676                 }
2677             }
2678         }
2679     }
2680
2681     public IWindowId getWindowId(IBinder token) {
2682         synchronized (mWindowMap) {
2683             WindowState window = mWindowMap.get(token);
2684             return window != null ? window.mWindowId : null;
2685         }
2686     }
2687
2688     public void pokeDrawLock(Session session, IBinder token) {
2689         synchronized (mWindowMap) {
2690             WindowState window = windowForClientLocked(session, token, false);
2691             if (window != null) {
2692                 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
2693             }
2694         }
2695     }
2696
2697     void repositionChild(Session session, IWindow client,
2698             int left, int top, int right, int bottom,
2699             long frameNumber, Rect outFrame) {
2700         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
2701         long origId = Binder.clearCallingIdentity();
2702
2703         try {
2704             synchronized(mWindowMap) {
2705                 WindowState win = windowForClientLocked(session, client, false);
2706                 if (win == null) {
2707                     return;
2708                 }
2709                 if (win.mAttachedWindow == null) {
2710                     throw new IllegalArgumentException(
2711                             "repositionChild called but window is not"
2712                             + "attached to a parent win=" + win);
2713                 }
2714
2715                 win.mAttrs.x = left;
2716                 win.mAttrs.y = top;
2717                 win.mAttrs.width = right - left;
2718                 win.mAttrs.height = bottom - top;
2719                 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2720
2721                 if (win.mHasSurface) {
2722                     if (SHOW_TRANSACTIONS) {
2723                         Slog.i(TAG_WM, ">>> OPEN TRANSACTION repositionChild");
2724                     }
2725
2726                     SurfaceControl.openTransaction();
2727
2728                     try {
2729
2730                         win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame);
2731                         win.mWinAnimator.computeShownFrameLocked();
2732
2733                         win.mWinAnimator.setSurfaceBoundariesLocked(false);
2734
2735                         if (frameNumber > 0) {
2736                             win.mWinAnimator.deferTransactionUntilParentFrame(frameNumber);
2737                         }
2738
2739                     } finally {
2740                         SurfaceControl.closeTransaction();
2741                         if (SHOW_TRANSACTIONS) {
2742                             Slog.i(TAG_WM, "<<< CLOSE TRANSACTION repositionChild");
2743                         }
2744                     }
2745                 }
2746
2747                 outFrame = win.mCompatFrame;
2748             }
2749         } finally {
2750             Binder.restoreCallingIdentity(origId);
2751             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2752         }
2753     }
2754
2755     public int relayoutWindow(Session session, IWindow client, int seq,
2756             WindowManager.LayoutParams attrs, int requestedWidth,
2757             int requestedHeight, int viewVisibility, int flags,
2758             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2759             Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
2760             Configuration outConfig, Surface outSurface) {
2761         int result = 0;
2762         boolean configChanged;
2763         boolean hasStatusBarPermission =
2764                 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2765                         == PackageManager.PERMISSION_GRANTED;
2766
2767         long origId = Binder.clearCallingIdentity();
2768         synchronized(mWindowMap) {
2769             WindowState win = windowForClientLocked(session, client, false);
2770             if (win == null) {
2771                 return 0;
2772             }
2773
2774             WindowStateAnimator winAnimator = win.mWinAnimator;
2775             if (viewVisibility != View.GONE) {
2776                 win.setRequestedSize(requestedWidth, requestedHeight);
2777             }
2778
2779             int attrChanges = 0;
2780             int flagChanges = 0;
2781             if (attrs != null) {
2782                 mPolicy.adjustWindowParamsLw(attrs);
2783                 // if they don't have the permission, mask out the status bar bits
2784                 if (seq == win.mSeq) {
2785                     int systemUiVisibility = attrs.systemUiVisibility
2786                             | attrs.subtreeSystemUiVisibility;
2787                     if ((systemUiVisibility & DISABLE_MASK) != 0) {
2788                         if (!hasStatusBarPermission) {
2789                             systemUiVisibility &= ~DISABLE_MASK;
2790                         }
2791                     }
2792                     win.mSystemUiVisibility = systemUiVisibility;
2793                 }
2794                 if (win.mAttrs.type != attrs.type) {
2795                     throw new IllegalArgumentException(
2796                             "Window type can not be changed after the window is added.");
2797                 }
2798
2799                 // Odd choice but less odd than embedding in copyFrom()
2800                 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
2801                         != 0) {
2802                     attrs.x = win.mAttrs.x;
2803                     attrs.y = win.mAttrs.y;
2804                     attrs.width = win.mAttrs.width;
2805                     attrs.height = win.mAttrs.height;
2806                 }
2807
2808                 flagChanges = win.mAttrs.flags ^= attrs.flags;
2809                 attrChanges = win.mAttrs.copyFrom(attrs);
2810                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2811                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2812                     win.mLayoutNeeded = true;
2813                 }
2814             }
2815
2816             if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
2817                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2818             winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2819             win.mEnforceSizeCompat =
2820                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2821             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2822                 winAnimator.mAlpha = attrs.alpha;
2823             }
2824             win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2825
2826             if (win.mAttrs.surfaceInsets.left != 0
2827                     || win.mAttrs.surfaceInsets.top != 0
2828                     || win.mAttrs.surfaceInsets.right != 0
2829                     || win.mAttrs.surfaceInsets.bottom != 0) {
2830                 winAnimator.setOpaqueLocked(false);
2831             }
2832
2833             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2834             final boolean isDefaultDisplay = win.isDefaultDisplay();
2835             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2836                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2837                     || (!win.mRelayoutCalled));
2838
2839             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2840                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2841             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2842             if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
2843                 winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
2844             }
2845
2846             win.mRelayoutCalled = true;
2847             win.mInRelayout = true;
2848
2849             final int oldVisibility = win.mViewVisibility;
2850             win.mViewVisibility = viewVisibility;
2851             if (DEBUG_SCREEN_ON) {
2852                 RuntimeException stack = new RuntimeException();
2853                 stack.fillInStackTrace();
2854                 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
2855                         + " newVis=" + viewVisibility, stack);
2856             }
2857             if (viewVisibility == View.VISIBLE &&
2858                     (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2859                 result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges,
2860                         oldVisibility);
2861                 try {
2862                     result = createSurfaceControl(outSurface, result, win, winAnimator);
2863                 } catch (Exception e) {
2864                     mInputMonitor.updateInputWindowsLw(true /*force*/);
2865
2866                     Slog.w(TAG_WM, "Exception thrown when creating surface for client "
2867                              + client + " (" + win.mAttrs.getTitle() + ")",
2868                              e);
2869                     Binder.restoreCallingIdentity(origId);
2870                     return 0;
2871                 }
2872                 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
2873                     focusMayChange = isDefaultDisplay;
2874                 }
2875                 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
2876                     mInputMethodWindow = win;
2877                     imMayMove = true;
2878                 }
2879                 win.adjustStartingWindowFlags();
2880             } else {
2881                 winAnimator.mEnterAnimationPending = false;
2882                 winAnimator.mEnteringAnimation = false;
2883                 final boolean usingSavedSurfaceBeforeVisible =
2884                         oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
2885                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2886                     if (winAnimator.hasSurface() && !win.mAnimatingExit
2887                             && usingSavedSurfaceBeforeVisible) {
2888                         Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
2889                     }
2890                 }
2891
2892                 if (winAnimator.hasSurface() && !win.mAnimatingExit
2893                         && !usingSavedSurfaceBeforeVisible) {
2894                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
2895                             + ": mAnimatingExit=" + win.mAnimatingExit);
2896                     // If we are not currently running the exit animation, we
2897                     // need to see about starting one.
2898                     // We don't want to animate visibility of windows which are pending
2899                     // replacement. In the case of activity relaunch child windows
2900                     // could request visibility changes as they are detached from the main
2901                     // application window during the tear down process. If we satisfied
2902                     // these visibility changes though, we would cause a visual glitch
2903                     // hiding the window before it's replacement was available.
2904                     // So we just do nothing on our side.
2905                     if (!win.mWillReplaceWindow) {
2906                         focusMayChange = tryStartExitingAnimation(
2907                                 win, winAnimator, isDefaultDisplay, focusMayChange);
2908                     }
2909                     result |= RELAYOUT_RES_SURFACE_CHANGED;
2910                 }
2911                 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
2912                 if (viewVisibility == View.VISIBLE && surfaceController != null) {
2913                     // We already told the client to go invisible, but the message may not be
2914                     // handled yet, or it might want to draw a last frame. If we already have a
2915                     // surface, let the client use that, but don't create new surface at this point.
2916                     surfaceController.getSurface(outSurface);
2917                 } else {
2918                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
2919
2920                     try {
2921                         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
2922                                 + win.mAttrs.getTitle());
2923                         outSurface.release();
2924                     } finally {
2925                         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2926                     }
2927                 }
2928             }
2929
2930             if (focusMayChange) {
2931                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2932                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2933                         false /*updateInputWindows*/)) {
2934                     imMayMove = false;
2935                 }
2936                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2937             }
2938
2939             // updateFocusedWindowLocked() already assigned layers so we only need to
2940             // reassign them at this point if the IM window state gets shuffled
2941             boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
2942             if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
2943                 // Little hack here -- we -should- be able to rely on the
2944                 // function to return true if the IME has moved and needs
2945                 // its layer recomputed.  However, if the IME was hidden
2946                 // and isn't actually moved in the list, its layer may be
2947                 // out of data so we make sure to recompute it.
2948                 mLayersController.assignLayersLocked(win.getWindowList());
2949             }
2950
2951             if (wallpaperMayMove) {
2952                 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2953                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2954             }
2955
2956             win.setDisplayLayoutNeeded();
2957             win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2958             configChanged = updateOrientationFromAppTokensLocked(false);
2959             mWindowPlacerLocked.performSurfacePlacement();
2960             if (toBeDisplayed && win.mIsWallpaper) {
2961                 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
2962                 mWallpaperControllerLocked.updateWallpaperOffset(
2963                         win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2964             }
2965             if (win.mAppToken != null) {
2966                 win.mAppToken.updateReportedVisibilityLocked();
2967             }
2968             if (winAnimator.mReportSurfaceResized) {
2969                 winAnimator.mReportSurfaceResized = false;
2970                 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
2971             }
2972             if (mPolicy.isNavBarForcedShownLw(win)) {
2973                 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
2974             }
2975             if (!win.isGoneForLayoutLw()) {
2976                 win.mResizedWhileGone = false;
2977             }
2978             outFrame.set(win.mCompatFrame);
2979             outOverscanInsets.set(win.mOverscanInsets);
2980             outContentInsets.set(win.mContentInsets);
2981             outVisibleInsets.set(win.mVisibleInsets);
2982             outStableInsets.set(win.mStableInsets);
2983             outOutsets.set(win.mOutsets);
2984             outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
2985             if (localLOGV) Slog.v(
2986                 TAG_WM, "Relayout given client " + client.asBinder()
2987                 + ", requestedWidth=" + requestedWidth
2988                 + ", requestedHeight=" + requestedHeight
2989                 + ", viewVisibility=" + viewVisibility
2990                 + "\nRelayout returning frame=" + outFrame
2991                 + ", surface=" + outSurface);
2992
2993             if (localLOGV || DEBUG_FOCUS) Slog.v(
2994                 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2995
2996             result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
2997
2998             mInputMonitor.updateInputWindowsLw(true /*force*/);
2999
3000             if (DEBUG_LAYOUT) {
3001                 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3002             }
3003             win.mInRelayout = false;
3004         }
3005
3006         if (configChanged) {
3007             sendNewConfiguration();
3008         }
3009         Binder.restoreCallingIdentity(origId);
3010         return result;
3011     }
3012
3013     private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
3014             boolean isDefaultDisplay, boolean focusMayChange) {
3015         // Try starting an animation; if there isn't one, we
3016         // can destroy the surface right away.
3017         int transit = WindowManagerPolicy.TRANSIT_EXIT;
3018         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
3019             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
3020         }
3021         if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
3022             focusMayChange = isDefaultDisplay;
3023             win.mAnimatingExit = true;
3024             win.mWinAnimator.mAnimating = true;
3025         } else if (win.mWinAnimator.isAnimationSet()) {
3026             // Currently in a hide animation... turn this into
3027             // an exit.
3028             win.mAnimatingExit = true;
3029             win.mWinAnimator.mAnimating = true;
3030         } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
3031             // If the wallpaper is currently behind this
3032             // window, we need to change both of them inside
3033             // of a transaction to avoid artifacts.
3034             win.mAnimatingExit = true;
3035             win.mWinAnimator.mAnimating = true;
3036         } else {
3037             if (mInputMethodWindow == win) {
3038                 mInputMethodWindow = null;
3039             }
3040             win.destroyOrSaveSurface();
3041         }
3042         //TODO (multidisplay): Magnification is supported only for the default
3043         if (mAccessibilityController != null
3044                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
3045             mAccessibilityController.onWindowTransitionLocked(win, transit);
3046         }
3047         return focusMayChange;
3048     }
3049
3050     private int createSurfaceControl(Surface outSurface, int result, WindowState win,
3051             WindowStateAnimator winAnimator) {
3052         if (!win.mHasSurface) {
3053             result |= RELAYOUT_RES_SURFACE_CHANGED;
3054         }
3055         WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
3056         if (surfaceController != null) {
3057             surfaceController.getSurface(outSurface);
3058             if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurface + ": copied");
3059         } else {
3060             // For some reason there isn't a surface.  Clear the
3061             // caller's object so they see the same state.
3062             Slog.w(TAG_WM, "Failed to create surface control for " + win);
3063             outSurface.release();
3064         }
3065         return result;
3066     }
3067
3068     private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win,
3069             WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) {
3070         result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0;
3071         if (win.mAnimatingExit) {
3072             Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit="
3073                     + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying);
3074
3075             winAnimator.cancelExitAnimationForNextAnimationLocked();
3076             win.mAnimatingExit = false;
3077         }
3078         if (win.mDestroying) {
3079             win.mDestroying = false;
3080             mDestroySurface.remove(win);
3081         }
3082         if (oldVisibility == View.GONE) {
3083             winAnimator.mEnterAnimationPending = true;
3084         }
3085
3086         win.mLastVisibleLayoutRotation = mRotation;
3087
3088         winAnimator.mEnteringAnimation = true;
3089         if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
3090             win.prepareWindowToDisplayDuringRelayout(outConfig);
3091         }
3092         if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) {
3093             // If the format can't be changed in place, preserve the old surface until the app draws
3094             // on the new one. This prevents blinking when we change elevation of freeform and
3095             // pinned windows.
3096             if (!winAnimator.tryChangeFormatInPlaceLocked()) {
3097                 winAnimator.preserveSurfaceLocked();
3098                 result |= RELAYOUT_RES_SURFACE_CHANGED
3099                         | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
3100             }
3101         }
3102
3103         // If we're starting a drag-resize, we'll be changing the surface size as well as
3104         // notifying the client to render to with an offset from the surface's top-left.
3105         if (win.isDragResizeChanged() || win.isResizedWhileNotDragResizing()) {
3106             win.setDragResizing();
3107             win.setResizedWhileNotDragResizing(false);
3108             // We can only change top level windows to the full-screen surface when
3109             // resizing (as we only have one full-screen surface). So there is no need
3110             // to preserve and destroy windows which are attached to another, they
3111             // will keep their surface and its size may change over time.
3112             if (win.mHasSurface && win.mAttachedWindow == null) {
3113                 winAnimator.preserveSurfaceLocked();
3114                 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
3115             }
3116         }
3117         final boolean freeformResizing = win.isDragResizing()
3118                 && win.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
3119         final boolean dockedResizing = win.isDragResizing()
3120                 && win.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
3121         result |= freeformResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0;
3122         result |= dockedResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0;
3123         if (win.isAnimatingWithSavedSurface()) {
3124             // If we're animating with a saved surface now, request client to report draw.
3125             // We still need to know when the real thing is drawn.
3126             result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
3127         }
3128         return result;
3129     }
3130
3131     public void performDeferredDestroyWindow(Session session, IWindow client) {
3132         long origId = Binder.clearCallingIdentity();
3133
3134         try {
3135             synchronized (mWindowMap) {
3136                 WindowState win = windowForClientLocked(session, client, false);
3137                 if (win == null || win.mWillReplaceWindow) {
3138                     return;
3139                 }
3140
3141                 win.mWinAnimator.destroyDeferredSurfaceLocked();
3142             }
3143         } finally {
3144             Binder.restoreCallingIdentity(origId);
3145         }
3146     }
3147
3148     public boolean outOfMemoryWindow(Session session, IWindow client) {
3149         long origId = Binder.clearCallingIdentity();
3150
3151         try {
3152             synchronized (mWindowMap) {
3153                 WindowState win = windowForClientLocked(session, client, false);
3154                 if (win == null) {
3155                     return false;
3156                 }
3157                 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3158             }
3159         } finally {
3160             Binder.restoreCallingIdentity(origId);
3161         }
3162     }
3163
3164     public void finishDrawingWindow(Session session, IWindow client) {
3165         final long origId = Binder.clearCallingIdentity();
3166         try {
3167             synchronized (mWindowMap) {
3168                 WindowState win = windowForClientLocked(session, client, false);
3169                 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
3170                         + (win != null ? win.mWinAnimator.drawStateToString() : "null"));
3171                 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3172                     if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3173                         getDefaultDisplayContentLocked().pendingLayoutChanges |=
3174                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3175                     }
3176                     win.setDisplayLayoutNeeded();
3177                     mWindowPlacerLocked.requestTraversal();
3178                 }
3179             }
3180         } finally {
3181             Binder.restoreCallingIdentity(origId);
3182         }
3183     }
3184
3185     private boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
3186             int transit, boolean enter, boolean isVoiceInteraction) {
3187         // Only apply an animation if the display isn't frozen.  If it is
3188         // frozen, there is no reason to animate and it can cause strange
3189         // artifacts when we unfreeze the display if some different animation
3190         // is running.
3191         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
3192         if (okToDisplay()) {
3193             DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3194             final int width = displayInfo.appWidth;
3195             final int height = displayInfo.appHeight;
3196             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
3197                     "applyAnimation: atoken=" + atoken);
3198
3199             // Determine the visible rect to calculate the thumbnail clip
3200             final WindowState win = atoken.findMainWindow();
3201             final Rect frame = new Rect(0, 0, width, height);
3202             final Rect displayFrame = new Rect(0, 0,
3203                     displayInfo.logicalWidth, displayInfo.logicalHeight);
3204             final Rect insets = new Rect();
3205             Rect surfaceInsets = null;
3206             final boolean freeform = win != null && win.inFreeformWorkspace();
3207             if (win != null) {
3208                 // Containing frame will usually cover the whole screen, including dialog windows.
3209                 // For freeform workspace windows it will not cover the whole screen and it also
3210                 // won't exactly match the final freeform window frame (e.g. when overlapping with
3211                 // the status bar). In that case we need to use the final frame.
3212                 if (freeform) {
3213                     frame.set(win.mFrame);
3214                 } else {
3215                     frame.set(win.mContainingFrame);
3216                 }
3217                 surfaceInsets = win.getAttrs().surfaceInsets;
3218                 insets.set(win.mContentInsets);
3219             }
3220
3221             if (atoken.mLaunchTaskBehind) {
3222                 // Differentiate the two animations. This one which is briefly on the screen
3223                 // gets the !enter animation, and the other activity which remains on the
3224                 // screen gets the enter animation. Both appear in the mOpeningApps set.
3225                 enter = false;
3226             }
3227             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
3228                     + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
3229                     + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
3230             Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode,
3231                     mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets,
3232                     isVoiceInteraction, freeform, atoken.mTask.mTaskId);
3233             if (a != null) {
3234                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
3235                 final int containingWidth = frame.width();
3236                 final int containingHeight = frame.height();
3237                 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight,
3238                         mAppTransition.canSkipFirstFrame(), mAppTransition.getAppStackClipMode());
3239             }
3240         } else {
3241             atoken.mAppAnimator.clearAnimation();
3242         }
3243         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
3244
3245         return atoken.mAppAnimator.animation != null;
3246     }
3247
3248     // -------------------------------------------------------------
3249     // Application Window Tokens
3250     // -------------------------------------------------------------
3251
3252     public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3253         synchronized (mWindowMap) {
3254             int t = tasks.size() - 1;
3255             if (t < 0) {
3256                 Slog.w(TAG_WM, "validateAppTokens: empty task list");
3257                 return;
3258             }
3259
3260             TaskGroup task = tasks.get(0);
3261             int taskId = task.taskId;
3262             Task targetTask = mTaskIdToTask.get(taskId);
3263             DisplayContent displayContent = targetTask.getDisplayContent();
3264             if (displayContent == null) {
3265                 Slog.w(TAG_WM, "validateAppTokens: no Display for taskId=" + taskId);
3266                 return;
3267             }
3268
3269             final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3270             int taskNdx;
3271             for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3272                 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3273                 task = tasks.get(t);
3274                 List<IApplicationToken> tokens = task.tokens;
3275
3276                 DisplayContent lastDisplayContent = displayContent;
3277                 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3278                 if (displayContent != lastDisplayContent) {
3279                     Slog.w(TAG_WM, "validateAppTokens: displayContent changed in TaskGroup list!");
3280                     return;
3281                 }
3282
3283                 int tokenNdx;
3284                 int v;
3285                 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3286                         tokenNdx >= 0 && v >= 0; ) {
3287                     final AppWindowToken atoken = localTokens.get(tokenNdx);
3288                     if (atoken.removed) {
3289                         --tokenNdx;
3290                         continue;
3291                     }
3292                     if (tokens.get(v) != atoken.token) {
3293                         break;
3294                     }
3295                     --tokenNdx;
3296                     v--;
3297                 }
3298
3299                 if (tokenNdx >= 0 || v >= 0) {
3300                     break;
3301                 }
3302             }
3303
3304             if (taskNdx >= 0 || t >= 0) {
3305                 Slog.w(TAG_WM, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3306                 Slog.w(TAG_WM, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3307                 Slog.w(TAG_WM, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3308             }
3309         }
3310     }
3311
3312     public void validateStackOrder(Integer[] remoteStackIds) {
3313         // TODO:
3314     }
3315
3316     private boolean checkCallingPermission(String permission, String func) {
3317         // Quick check: if the calling permission is me, it's all okay.
3318         if (Binder.getCallingPid() == Process.myPid()) {
3319             return true;
3320         }
3321
3322         if (mContext.checkCallingPermission(permission)
3323                 == PackageManager.PERMISSION_GRANTED) {
3324             return true;
3325         }
3326         String msg = "Permission Denial: " + func + " from pid="
3327                 + Binder.getCallingPid()
3328                 + ", uid=" + Binder.getCallingUid()
3329                 + " requires " + permission;
3330         Slog.w(TAG_WM, msg);
3331         return false;
3332     }
3333
3334     boolean okToDisplay() {
3335         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
3336     }
3337
3338     AppWindowToken findAppWindowToken(IBinder token) {
3339         WindowToken wtoken = mTokenMap.get(token);
3340         if (wtoken == null) {
3341             return null;
3342         }
3343         return wtoken.appWindowToken;
3344     }
3345
3346     @Override
3347     public void addWindowToken(IBinder token, int type) {
3348         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3349                 "addWindowToken()")) {
3350             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3351         }
3352
3353         synchronized(mWindowMap) {
3354             WindowToken wtoken = mTokenMap.get(token);
3355             if (wtoken != null) {
3356                 Slog.w(TAG_WM, "Attempted to add existing input method token: " + token);
3357                 return;
3358             }
3359             wtoken = new WindowToken(this, token, type, true);
3360             mTokenMap.put(token, wtoken);
3361             if (type == TYPE_WALLPAPER) {
3362                 mWallpaperControllerLocked.addWallpaperToken(wtoken);
3363             }
3364         }
3365     }
3366
3367     @Override
3368     public void removeWindowToken(IBinder token) {
3369         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3370                 "removeWindowToken()")) {
3371             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3372         }
3373
3374         final long origId = Binder.clearCallingIdentity();
3375         synchronized(mWindowMap) {
3376             DisplayContent displayContent = null;
3377             WindowToken wtoken = mTokenMap.remove(token);
3378             if (wtoken != null) {
3379                 boolean delayed = false;
3380                 if (!wtoken.hidden) {
3381                     final int N = wtoken.windows.size();
3382                     boolean changed = false;
3383
3384                     for (int i=0; i<N; i++) {
3385                         WindowState win = wtoken.windows.get(i);
3386                         displayContent = win.getDisplayContent();
3387
3388                         if (win.mWinAnimator.isAnimationSet()) {
3389                             delayed = true;
3390                         }
3391
3392                         if (win.isVisibleNow()) {
3393                             win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3394                                     false);
3395                             //TODO (multidisplay): Magnification is supported only for the default
3396                             if (mAccessibilityController != null && win.isDefaultDisplay()) {
3397                                 mAccessibilityController.onWindowTransitionLocked(win,
3398                                         WindowManagerPolicy.TRANSIT_EXIT);
3399                             }
3400                             changed = true;
3401                             if (displayContent != null) {
3402                                 displayContent.layoutNeeded = true;
3403                             }
3404                         }
3405                     }
3406
3407                     wtoken.hidden = true;
3408
3409                     if (changed) {
3410                         mWindowPlacerLocked.performSurfacePlacement();
3411                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3412                                 false /*updateInputWindows*/);
3413                     }
3414
3415                     if (delayed && displayContent != null) {
3416                         displayContent.mExitingTokens.add(wtoken);
3417                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
3418                         mWallpaperControllerLocked.removeWallpaperToken(wtoken);
3419                     }
3420                 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3421                     mWallpaperControllerLocked.removeWallpaperToken(wtoken);
3422                 }
3423
3424                 mInputMonitor.updateInputWindowsLw(true /*force*/);
3425             } else {
3426                 Slog.w(TAG_WM, "Attempted to remove non-existing token: " + token);
3427             }
3428         }
3429         Binder.restoreCallingIdentity(origId);
3430     }
3431
3432     private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken,
3433             Rect bounds, Configuration config) {
3434         if (DEBUG_STACK) Slog.i(TAG_WM, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId
3435                 + " atoken=" + atoken + " bounds=" + bounds);
3436         final TaskStack stack = mStackIdToStack.get(stackId);
3437         if (stack == null) {
3438             throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3439         }
3440         EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
3441         Task task = new Task(taskId, stack, userId, this, bounds, config);
3442         mTaskIdToTask.put(taskId, task);
3443         stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers);
3444         return task;
3445     }
3446
3447     @Override
3448     public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3449             int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
3450             int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
3451             Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable,
3452             boolean homeTask, int targetSdkVersion, int rotationAnimationHint) {
3453         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3454                 "addAppToken()")) {
3455             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3456         }
3457
3458         // Get the dispatching timeout here while we are not holding any locks so that it
3459         // can be cached by the AppWindowToken.  The timeout value is used later by the
3460         // input dispatcher in code that does hold locks.  If we did not cache the value
3461         // here we would run the chance of introducing a deadlock between the window manager
3462         // (which holds locks while updating the input dispatcher state) and the activity manager
3463         // (which holds locks while querying the application token).
3464         long inputDispatchingTimeoutNanos;
3465         try {
3466             inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3467         } catch (RemoteException ex) {
3468             Slog.w(TAG_WM, "Could not get dispatching timeout.", ex);
3469             inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3470         }
3471
3472         synchronized(mWindowMap) {
3473             AppWindowToken atoken = findAppWindowToken(token.asBinder());
3474             if (atoken != null) {
3475                 Slog.w(TAG_WM, "Attempted to add existing app token: " + token);
3476                 return;
3477             }
3478             atoken = new AppWindowToken(this, token, voiceInteraction);
3479             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3480             atoken.appFullscreen = fullscreen;
3481             atoken.showForAllUsers = showForAllUsers;
3482             atoken.targetSdk = targetSdkVersion;
3483             atoken.requestedOrientation = requestedOrientation;
3484             atoken.layoutConfigChanges = (configChanges &
3485                     (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
3486             atoken.mLaunchTaskBehind = launchTaskBehind;
3487             atoken.mAlwaysFocusable = alwaysFocusable;
3488             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
3489                     + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3490             atoken.mRotationAnimationHint = rotationAnimationHint;
3491
3492             Task task = mTaskIdToTask.get(taskId);
3493             if (task == null) {
3494                 task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config);
3495             }
3496             task.addAppToken(addPos, atoken, taskResizeMode, homeTask);
3497
3498             mTokenMap.put(token.asBinder(), atoken);
3499
3500             // Application tokens start out hidden.
3501             atoken.hidden = true;
3502             atoken.hiddenRequested = true;
3503         }
3504     }
3505
3506     @Override
3507     public void setAppTask(IBinder token, int taskId, int stackId, Rect taskBounds,
3508             Configuration config, int taskResizeMode, boolean homeTask) {
3509         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3510                 "setAppTask()")) {
3511             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3512         }
3513
3514         synchronized(mWindowMap) {
3515             final AppWindowToken atoken = findAppWindowToken(token);
3516             if (atoken == null) {
3517                 Slog.w(TAG_WM, "Attempted to set task id of non-existing app token: " + token);
3518                 return;
3519             }
3520             final Task oldTask = atoken.mTask;
3521             oldTask.removeAppToken(atoken);
3522
3523             Task newTask = mTaskIdToTask.get(taskId);
3524             if (newTask == null) {
3525                 newTask = createTaskLocked(
3526                         taskId, stackId, oldTask.mUserId, atoken, taskBounds, config);
3527             }
3528             newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken, taskResizeMode, homeTask);
3529         }
3530     }
3531
3532     public int getOrientationLocked() {
3533         if (mDisplayFrozen) {
3534             if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
3535                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3536                         "Display is frozen, return " + mLastWindowForcedOrientation);
3537                 // If the display is frozen, some activities may be in the middle
3538                 // of restarting, and thus have removed their old window.  If the
3539                 // window has the flag to hide the lock screen, then the lock screen
3540                 // can re-appear and inflict its own orientation on us.  Keep the
3541                 // orientation stable until this all settles down.
3542                 return mLastWindowForcedOrientation;
3543             } else if (mPolicy.isKeyguardLocked()) {
3544                 // Use the last orientation the while the display is frozen with the
3545                 // keyguard locked. This could be the keyguard forced orientation or
3546                 // from a SHOW_WHEN_LOCKED window. We don't want to check the show when
3547                 // locked window directly though as things aren't stable while
3548                 // the display is frozen, for example the window could be momentarily unavailable
3549                 // due to activity relaunch.
3550                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
3551                         + "return " + mLastOrientation);
3552                 return mLastOrientation;
3553             }
3554         } else {
3555             // TODO(multidisplay): Change to the correct display.
3556             final WindowList windows = getDefaultWindowListLocked();
3557             for (int pos = windows.size() - 1; pos >= 0; --pos) {
3558                 WindowState win = windows.get(pos);
3559                 if (win.mAppToken != null) {
3560                     // We hit an application window. so the orientation will be determined by the
3561                     // app window. No point in continuing further.
3562                     break;
3563                 }
3564                 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3565                     continue;
3566                 }
3567                 int req = win.mAttrs.screenOrientation;
3568                 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
3569                     continue;
3570                 }
3571
3572                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
3573                 if (mPolicy.isKeyguardHostWindow(win.mAttrs)) {
3574                     mLastKeyguardForcedOrientation = req;
3575                 }
3576                 return (mLastWindowForcedOrientation = req);
3577             }
3578             mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3579
3580             if (mPolicy.isKeyguardLocked()) {
3581                 // The screen is locked and no top system window is requesting an orientation.
3582                 // Return either the orientation of the show-when-locked app (if there is any) or
3583                 // the orientation of the keyguard. No point in searching from the rest of apps.
3584                 WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
3585                 AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
3586                         null : winShowWhenLocked.mAppToken;
3587                 if (appShowWhenLocked != null) {
3588                     int req = appShowWhenLocked.requestedOrientation;
3589                     if (req == SCREEN_ORIENTATION_BEHIND) {
3590                         req = mLastKeyguardForcedOrientation;
3591                     }
3592                     if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + appShowWhenLocked
3593                             + " -- show when locked, return " + req);
3594                     return req;
3595                 }
3596                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3597                         "No one is requesting an orientation when the screen is locked");
3598                 return mLastKeyguardForcedOrientation;
3599             }
3600         }
3601
3602         // Top system windows are not requesting an orientation. Start searching from apps.
3603         return getAppSpecifiedOrientation();
3604     }
3605
3606     private int getAppSpecifiedOrientation() {
3607         int lastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3608         boolean findingBehind = false;
3609         boolean lastFullscreen = false;
3610         DisplayContent displayContent = getDefaultDisplayContentLocked();
3611         final ArrayList<Task> tasks = displayContent.getTasks();
3612         final boolean inMultiWindow = isStackVisibleLocked(DOCKED_STACK_ID)
3613                 || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID);
3614         final boolean dockMinimized =
3615                 getDefaultDisplayContentLocked().mDividerControllerLocked.isMinimizedDock();
3616         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3617             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3618             final int firstToken = tokens.size() - 1;
3619             for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3620                 final AppWindowToken atoken = tokens.get(tokenNdx);
3621
3622                 if (DEBUG_APP_ORIENTATION) Slog.v(TAG_WM, "Checking app orientation: " + atoken);
3623
3624                 // if we're about to tear down this window and not seek for
3625                 // the behind activity, don't use it for orientation
3626                 if (!findingBehind && !atoken.hidden && atoken.hiddenRequested) {
3627                     if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3628                             "Skipping " + atoken + " -- going to hide");
3629                     continue;
3630                 }
3631
3632                 if (tokenNdx == firstToken) {
3633                     // If we have hit a new Task, and the bottom of the previous group didn't
3634                     // explicitly say to use the orientation behind it, and the last app was
3635                     // full screen, then we'll stick with the user's orientation.
3636                     if (lastOrientation != SCREEN_ORIENTATION_BEHIND && lastFullscreen) {
3637                         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + atoken
3638                                 + " -- end of group, return " + lastOrientation);
3639                         return lastOrientation;
3640                     }
3641                 }
3642
3643                 // We ignore any hidden applications on the top.
3644                 if (atoken.hiddenRequested) {
3645                     if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3646                             "Skipping " + atoken + " -- hidden on top");
3647                     continue;
3648                 }
3649
3650                 // No app except the home app may specify the screen orientation in multi-window,
3651                 // and only if the docked stack is minimized to avoid weirdness when home task
3652                 // temporarily gets moved to the front.
3653                 if (inMultiWindow && (!atoken.mTask.isHomeTask() || !dockMinimized)) {
3654                     continue;
3655                 }
3656
3657                 if (tokenNdx == 0) {
3658                     // Last token in this task.
3659                     lastOrientation = atoken.requestedOrientation;
3660                 }
3661
3662                 int or = atoken.requestedOrientation;
3663                 // If this application is fullscreen, and didn't explicitly say
3664                 // to use the orientation behind it, then just take whatever
3665                 // orientation it has and ignores whatever is under it.
3666                 lastFullscreen = atoken.appFullscreen;
3667                 if (lastFullscreen && or != SCREEN_ORIENTATION_BEHIND) {
3668                     if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3669                             "Done at " + atoken + " -- full screen, return " + or);
3670                     return or;
3671                 }
3672                 // If this application has requested an explicit orientation, then use it.
3673                 if (or != SCREEN_ORIENTATION_UNSPECIFIED && or != SCREEN_ORIENTATION_BEHIND) {
3674                     if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3675                             "Done at " + atoken + " -- explicitly set, return " + or);
3676                     return or;
3677                 }
3678                 findingBehind |= (or == SCREEN_ORIENTATION_BEHIND);
3679             }
3680         }
3681         if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3682                 "No app is requesting an orientation, return " + mLastOrientation);
3683         // The next app has not been requested to be visible, so we keep the current orientation
3684         // to prevent freezing/unfreezing the display too early unless we are in multi-window, in
3685         // which we don't let the app customize the orientation unless it was the home task that
3686         // is handled above.
3687         return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mLastOrientation;
3688     }
3689
3690     @Override
3691     public Configuration updateOrientationFromAppTokens(
3692             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3693         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3694                 "updateOrientationFromAppTokens()")) {
3695             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3696         }
3697
3698         Configuration config = null;
3699         long ident = Binder.clearCallingIdentity();
3700
3701         synchronized(mWindowMap) {
3702             config = updateOrientationFromAppTokensLocked(currentConfig,
3703                     freezeThisOneIfNeeded);
3704         }
3705
3706         Binder.restoreCallingIdentity(ident);
3707         return config;
3708     }
3709
3710     private Configuration updateOrientationFromAppTokensLocked(
3711             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3712         if (!mDisplayReady) {
3713             return null;
3714         }
3715         Configuration config = null;
3716
3717         if (updateOrientationFromAppTokensLocked(false)) {
3718             if (freezeThisOneIfNeeded != null) {
3719                 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3720                 if (atoken != null) {
3721                     startAppFreezingScreenLocked(atoken);
3722                 }
3723             }
3724             config = computeNewConfigurationLocked();
3725
3726         } else if (currentConfig != null) {
3727             // No obvious action we need to take, but if our current
3728             // state mismatches the activity manager's, update it,
3729             // disregarding font scale, which should remain set to
3730             // the value of the previous configuration.
3731             mTempConfiguration.setToDefaults();
3732             mTempConfiguration.updateFrom(currentConfig);
3733             computeScreenConfigurationLocked(mTempConfiguration);
3734             if (currentConfig.diff(mTempConfiguration) != 0) {
3735                 mWaitingForConfig = true;
3736                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3737                 displayContent.layoutNeeded = true;
3738                 int anim[] = new int[2];
3739                 if (displayContent.isDimming()) {
3740                     anim[0] = anim[1] = 0;
3741                 } else {
3742                     mPolicy.selectRotationAnimationLw(anim);
3743                 }
3744                 startFreezingDisplayLocked(false, anim[0], anim[1]);
3745                 config = new Configuration(mTempConfiguration);
3746             }
3747         }
3748
3749         return config;
3750     }
3751
3752     /*
3753      * Determine the new desired orientation of the display, returning
3754      * a non-null new Configuration if it has changed from the current
3755      * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3756      * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3757      * SCREEN.  This will typically be done for you if you call
3758      * sendNewConfiguration().
3759      *
3760      * The orientation is computed from non-application windows first. If none of
3761      * the non-application windows specify orientation, the orientation is computed from
3762      * application tokens.
3763      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3764      * android.os.IBinder)
3765      */
3766     boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3767         long ident = Binder.clearCallingIdentity();
3768         try {
3769             int req = getOrientationLocked();
3770             if (req != mLastOrientation) {
3771                 mLastOrientation = req;
3772                 //send a message to Policy indicating orientation change to take
3773                 //action like disabling/enabling sensors etc.,
3774                 mPolicy.setCurrentOrientationLw(req);
3775                 if (updateRotationUncheckedLocked(inTransaction)) {
3776                     // changed
3777                     return true;
3778                 }
3779             }
3780
3781             return false;
3782         } finally {
3783             Binder.restoreCallingIdentity(ident);
3784         }
3785     }
3786
3787     @Override
3788     public int[] setNewConfiguration(Configuration config) {
3789         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3790                 "setNewConfiguration()")) {
3791             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3792         }
3793
3794         synchronized(mWindowMap) {
3795             if (mWaitingForConfig) {
3796                 mWaitingForConfig = false;
3797                 mLastFinishedFreezeSource = "new-config";
3798             }
3799             boolean configChanged = mCurConfiguration.diff(config) != 0;
3800             if (!configChanged) {
3801                 return null;
3802             }
3803             prepareFreezingAllTaskBounds();
3804             mCurConfiguration = new Configuration(config);
3805             return onConfigurationChanged();
3806         }
3807     }
3808
3809     @Override
3810     public Rect getBoundsForNewConfiguration(int stackId) {
3811         synchronized(mWindowMap) {
3812             final TaskStack stack = mStackIdToStack.get(stackId);
3813             final Rect outBounds = new Rect();
3814             stack.getBoundsForNewConfiguration(outBounds);
3815             return outBounds;
3816         }
3817     }
3818
3819     private void prepareFreezingAllTaskBounds() {
3820         for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
3821             ArrayList<TaskStack> stacks = mDisplayContents.valueAt(i).getStacks();
3822             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
3823                 final TaskStack stack = stacks.get(stackNdx);
3824                 stack.prepareFreezingTaskBounds();
3825             }
3826         }
3827
3828     }
3829     private int[] onConfigurationChanged() {
3830         mPolicy.onConfigurationChanged();
3831
3832         final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
3833         if (!mReconfigureOnConfigurationChanged.contains(defaultDisplayContent)) {
3834             // The default display size information is heavily dependent on the resources in the
3835             // current configuration, so we need to reconfigure it everytime the configuration
3836             // changes. See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
3837             mReconfigureOnConfigurationChanged.add(defaultDisplayContent);
3838         }
3839         for (int i = mReconfigureOnConfigurationChanged.size() - 1; i >= 0; i--) {
3840             reconfigureDisplayLocked(mReconfigureOnConfigurationChanged.remove(i));
3841         }
3842
3843         defaultDisplayContent.getDockedDividerController().onConfigurationChanged();
3844         mChangedStackList.clear();
3845         for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
3846             final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
3847             if (stack.onConfigurationChanged()) {
3848                 mChangedStackList.add(stack.mStackId);
3849             }
3850         }
3851         return mChangedStackList.isEmpty() ?
3852                 null : ArrayUtils.convertToIntArray(mChangedStackList);
3853     }
3854
3855     @Override
3856     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3857         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3858                 "setAppOrientation()")) {
3859             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3860         }
3861
3862         synchronized(mWindowMap) {
3863             AppWindowToken atoken = findAppWindowToken(token.asBinder());
3864             if (atoken == null) {
3865                 Slog.w(TAG_WM, "Attempted to set orientation of non-existing app token: " + token);
3866                 return;
3867             }
3868
3869             atoken.requestedOrientation = requestedOrientation;
3870         }
3871     }
3872
3873     @Override
3874     public int getAppOrientation(IApplicationToken token) {
3875         synchronized(mWindowMap) {
3876             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3877             if (wtoken == null) {
3878                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3879             }
3880
3881             return wtoken.requestedOrientation;
3882         }
3883     }
3884
3885     void setFocusTaskRegionLocked() {
3886         if (mFocusedApp != null) {
3887             final Task task = mFocusedApp.mTask;
3888             final DisplayContent displayContent = task.getDisplayContent();
3889             if (displayContent != null) {
3890                 displayContent.setTouchExcludeRegion(task);
3891             }
3892         }
3893     }
3894
3895     @Override
3896     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3897         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3898                 "setFocusedApp()")) {
3899             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3900         }
3901
3902         synchronized(mWindowMap) {
3903             final AppWindowToken newFocus;
3904             if (token == null) {
3905                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
3906                 newFocus = null;
3907             } else {
3908                 newFocus = findAppWindowToken(token);
3909                 if (newFocus == null) {
3910                     Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
3911                 }
3912                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
3913                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3914             }
3915
3916             final boolean changed = mFocusedApp != newFocus;
3917             if (changed) {
3918                 mFocusedApp = newFocus;
3919                 mInputMonitor.setFocusedAppLw(newFocus);
3920                 setFocusTaskRegionLocked();
3921             }
3922
3923             if (moveFocusNow && changed) {
3924                 final long origId = Binder.clearCallingIdentity();
3925                 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3926                 Binder.restoreCallingIdentity(origId);
3927             }
3928         }
3929     }
3930
3931     /**
3932      * @param transit What kind of transition is happening. Use one of the constants
3933      *                AppTransition.TRANSIT_*.
3934      * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
3935      *                          be set.
3936      */
3937     @Override
3938     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3939         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3940                 "prepareAppTransition()")) {
3941             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3942         }
3943         synchronized(mWindowMap) {
3944             boolean prepared = mAppTransition.prepareAppTransitionLocked(
3945                     transit, alwaysKeepCurrent);
3946             if (prepared && okToDisplay()) {
3947                 mSkipAppTransitionAnimation = false;
3948             }
3949         }
3950     }
3951
3952     @Override
3953     public int getPendingAppTransition() {
3954         return mAppTransition.getAppTransition();
3955     }
3956
3957     @Override
3958     public void overridePendingAppTransition(String packageName,
3959             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3960         synchronized(mWindowMap) {
3961             mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3962                     startedCallback);
3963         }
3964     }
3965
3966     @Override
3967     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3968             int startHeight) {
3969         synchronized(mWindowMap) {
3970             mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3971                     startHeight);
3972         }
3973     }
3974
3975     @Override
3976     public void overridePendingAppTransitionClipReveal(int startX, int startY,
3977             int startWidth, int startHeight) {
3978         synchronized(mWindowMap) {
3979             mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
3980                     startHeight);
3981         }
3982     }
3983
3984     @Override
3985     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3986             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3987         synchronized(mWindowMap) {
3988             mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3989                     startedCallback, scaleUp);
3990         }
3991     }
3992
3993     @Override
3994     public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
3995             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
3996             boolean scaleUp) {
3997         synchronized(mWindowMap) {
3998             mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY,
3999                     targetWidth, targetHeight, startedCallback, scaleUp);
4000         }
4001     }
4002
4003     @Override
4004     public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
4005             IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
4006             boolean scaleUp) {
4007         synchronized (mWindowMap) {
4008             mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
4009                     onAnimationFinishedCallback, scaleUp);
4010             prolongAnimationsFromSpecs(specs, scaleUp);
4011
4012         }
4013     }
4014
4015     void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
4016         // This is used by freeform <-> recents windows transition. We need to synchronize
4017         // the animation with the appearance of the content of recents, so we will make
4018         // animation stay on the first or last frame a little longer.
4019         mTmpTaskIds.clear();
4020         for (int i = specs.length - 1; i >= 0; i--) {
4021             mTmpTaskIds.put(specs[i].taskId, 0);
4022         }
4023         for (final WindowState win : mWindowMap.values()) {
4024             final Task task = win.getTask();
4025             if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
4026                     && task.inFreeformWorkspace()) {
4027                 final AppWindowToken appToken = win.mAppToken;
4028                 if (appToken != null && appToken.mAppAnimator != null) {
4029                     appToken.mAppAnimator.startProlongAnimation(scaleUp ?
4030                             PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
4031                 }
4032             }
4033         }
4034     }
4035
4036     @Override
4037     public void overridePendingAppTransitionInPlace(String packageName, int anim) {
4038         synchronized(mWindowMap) {
4039             mAppTransition.overrideInPlaceAppTransition(packageName, anim);
4040         }
4041     }
4042
4043     @Override
4044     public void overridePendingAppTransitionMultiThumbFuture(
4045             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
4046             boolean scaleUp) {
4047         synchronized(mWindowMap) {
4048             mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback,
4049                     scaleUp);
4050         }
4051     }
4052
4053     @Override
4054     public void endProlongedAnimations() {
4055         synchronized (mWindowMap) {
4056             for (final WindowState win : mWindowMap.values()) {
4057                 final AppWindowToken appToken = win.mAppToken;
4058                 if (appToken != null && appToken.mAppAnimator != null) {
4059                     appToken.mAppAnimator.endProlongedAnimation();
4060                 }
4061             }
4062             mAppTransition.notifyProlongedAnimationsEnded();
4063         }
4064     }
4065
4066     @Override
4067     public void executeAppTransition() {
4068         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4069                 "executeAppTransition()")) {
4070             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4071         }
4072
4073         synchronized(mWindowMap) {
4074             if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition
4075                     + " Callers=" + Debug.getCallers(5));
4076             if (mAppTransition.isTransitionSet()) {
4077                 mAppTransition.setReady();
4078                 final long origId = Binder.clearCallingIdentity();
4079                 try {
4080                     mWindowPlacerLocked.performSurfacePlacement();
4081                 } finally {
4082                     Binder.restoreCallingIdentity(origId);
4083                 }
4084             }
4085         }
4086     }
4087
4088     @Override
4089     public boolean setAppStartingWindow(IBinder token, String pkg,
4090             int theme, CompatibilityInfo compatInfo,
4091             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
4092             int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
4093         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4094                 "setAppStartingWindow()")) {
4095             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4096         }
4097
4098         synchronized(mWindowMap) {
4099             if (DEBUG_STARTING_WINDOW) Slog.v(
4100                     TAG_WM, "setAppStartingWindow: token=" + token + " pkg=" + pkg
4101                     + " transferFrom=" + transferFrom);
4102
4103             AppWindowToken wtoken = findAppWindowToken(token);
4104             if (wtoken == null) {
4105                 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + token);
4106                 return false;
4107             }
4108
4109             // If the display is frozen, we won't do anything until the
4110             // actual window is displayed so there is no reason to put in
4111             // the starting window.
4112             if (!okToDisplay()) {
4113                 return false;
4114             }
4115
4116             if (wtoken.startingData != null) {
4117                 return false;
4118             }
4119
4120             // If this is a translucent window, then don't
4121             // show a starting window -- the current effect (a full-screen
4122             // opaque starting window that fades away to the real contents
4123             // when it is ready) does not work for this.
4124             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
4125                     + Integer.toHexString(theme));
4126             if (theme != 0) {
4127                 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4128                         com.android.internal.R.styleable.Window, mCurrentUserId);
4129                 if (ent == null) {
4130                     // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
4131                     // pretend like we didn't see that.
4132                     return false;
4133                 }
4134                 final boolean windowIsTranslucent = ent.array.getBoolean(
4135                         com.android.internal.R.styleable.Window_windowIsTranslucent, false);
4136                 final boolean windowIsFloating = ent.array.getBoolean(
4137                         com.android.internal.R.styleable.Window_windowIsFloating, false);
4138                 final boolean windowShowWallpaper = ent.array.getBoolean(
4139                         com.android.internal.R.styleable.Window_windowShowWallpaper, false);
4140                 final boolean windowDisableStarting = ent.array.getBoolean(
4141                         com.android.internal.R.styleable.Window_windowDisablePreview, false);
4142                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
4143                         + " Floating=" + windowIsFloating
4144                         + " ShowWallpaper=" + windowShowWallpaper);
4145                 if (windowIsTranslucent) {
4146                     return false;
4147                 }
4148                 if (windowIsFloating || windowDisableStarting) {
4149                     return false;
4150                 }
4151                 if (windowShowWallpaper) {
4152                     if (mWallpaperControllerLocked.getWallpaperTarget() == null) {
4153                         // If this theme is requesting a wallpaper, and the wallpaper
4154                         // is not currently visible, then this effectively serves as
4155                         // an opaque window and our starting window transition animation
4156                         // can still work.  We just need to make sure the starting window
4157                         // is also showing the wallpaper.
4158                         windowFlags |= FLAG_SHOW_WALLPAPER;
4159                     } else {
4160                         return false;
4161                     }
4162                 }
4163             }
4164
4165             if (transferStartingWindow(transferFrom, wtoken)) {
4166                 return true;
4167             }
4168
4169             // There is no existing starting window, and the caller doesn't
4170             // want us to create one, so that's it!
4171             if (!createIfNeeded) {
4172                 return false;
4173             }
4174
4175             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
4176             wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4177                     labelRes, icon, logo, windowFlags);
4178             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4179             // Note: we really want to do sendMessageAtFrontOfQueue() because we
4180             // want to process the message ASAP, before any other queued
4181             // messages.
4182             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
4183             mH.sendMessageAtFrontOfQueue(m);
4184         }
4185         return true;
4186     }
4187
4188     private boolean transferStartingWindow(IBinder transferFrom, AppWindowToken wtoken) {
4189         if (transferFrom == null) {
4190             return false;
4191         }
4192         AppWindowToken ttoken = findAppWindowToken(transferFrom);
4193         if (ttoken == null) {
4194             return false;
4195         }
4196         WindowState startingWindow = ttoken.startingWindow;
4197         if (startingWindow != null && ttoken.startingView != null) {
4198             // In this case, the starting icon has already been displayed, so start
4199             // letting windows get shown immediately without any more transitions.
4200             mSkipAppTransitionAnimation = true;
4201
4202             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
4203                     "Moving existing starting " + startingWindow + " from " + ttoken
4204                             + " to " + wtoken);
4205             final long origId = Binder.clearCallingIdentity();
4206
4207             // Transfer the starting window over to the new token.
4208             wtoken.startingData = ttoken.startingData;
4209             wtoken.startingView = ttoken.startingView;
4210             wtoken.startingDisplayed = ttoken.startingDisplayed;
4211             ttoken.startingDisplayed = false;
4212             wtoken.startingWindow = startingWindow;
4213             wtoken.reportedVisible = ttoken.reportedVisible;
4214             ttoken.startingData = null;
4215             ttoken.startingView = null;
4216             ttoken.startingWindow = null;
4217             ttoken.startingMoved = true;
4218             startingWindow.mToken = wtoken;
4219             startingWindow.mRootToken = wtoken;
4220             startingWindow.mAppToken = wtoken;
4221
4222             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4223                 Slog.v(TAG_WM, "Removing starting window: " + startingWindow);
4224             }
4225             startingWindow.getWindowList().remove(startingWindow);
4226             mWindowsChanged = true;
4227             if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
4228                     "Removing starting " + startingWindow + " from " + ttoken);
4229             ttoken.windows.remove(startingWindow);
4230             ttoken.allAppWindows.remove(startingWindow);
4231             addWindowToListInOrderLocked(startingWindow, true);
4232
4233             // Propagate other interesting state between the
4234             // tokens.  If the old token is displayed, we should
4235             // immediately force the new one to be displayed.  If
4236             // it is animating, we need to move that animation to
4237             // the new one.
4238             if (ttoken.allDrawn) {
4239                 wtoken.allDrawn = true;
4240                 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4241             }
4242             if (ttoken.firstWindowDrawn) {
4243                 wtoken.firstWindowDrawn = true;
4244             }
4245             if (!ttoken.hidden) {
4246                 wtoken.hidden = false;
4247                 wtoken.hiddenRequested = false;
4248             }
4249             if (wtoken.clientHidden != ttoken.clientHidden) {
4250                 wtoken.clientHidden = ttoken.clientHidden;
4251                 wtoken.sendAppVisibilityToClients();
4252             }
4253             ttoken.mAppAnimator.transferCurrentAnimation(
4254                     wtoken.mAppAnimator, startingWindow.mWinAnimator);
4255
4256             updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4257                     true /*updateInputWindows*/);
4258             getDefaultDisplayContentLocked().layoutNeeded = true;
4259             mWindowPlacerLocked.performSurfacePlacement();
4260             Binder.restoreCallingIdentity(origId);
4261             return true;
4262         } else if (ttoken.startingData != null) {
4263             // The previous app was getting ready to show a
4264             // starting window, but hasn't yet done so.  Steal it!
4265             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving pending starting from " + ttoken
4266                     + " to " + wtoken);
4267             wtoken.startingData = ttoken.startingData;
4268             ttoken.startingData = null;
4269             ttoken.startingMoved = true;
4270             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4271             // Note: we really want to do sendMessageAtFrontOfQueue() because we
4272             // want to process the message ASAP, before any other queued
4273             // messages.
4274             mH.sendMessageAtFrontOfQueue(m);
4275             return true;
4276         }
4277         final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4278         final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4279         if (tAppAnimator.thumbnail != null) {
4280             // The old token is animating with a thumbnail, transfer that to the new token.
4281             if (wAppAnimator.thumbnail != null) {
4282                 wAppAnimator.thumbnail.destroy();
4283             }
4284             wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4285             wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4286             wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4287             tAppAnimator.thumbnail = null;
4288         }
4289         return false;
4290     }
4291
4292     public void removeAppStartingWindow(IBinder token) {
4293         synchronized (mWindowMap) {
4294             final AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
4295             scheduleRemoveStartingWindowLocked(wtoken);
4296         }
4297     }
4298
4299     public void setAppFullscreen(IBinder token, boolean toOpaque) {
4300         synchronized (mWindowMap) {
4301             AppWindowToken atoken = findAppWindowToken(token);
4302             if (atoken != null) {
4303                 atoken.appFullscreen = toOpaque;
4304                 setWindowOpaqueLocked(token, toOpaque);
4305                 mWindowPlacerLocked.requestTraversal();
4306             }
4307         }
4308     }
4309
4310     public void setWindowOpaque(IBinder token, boolean isOpaque) {
4311         synchronized (mWindowMap) {
4312             setWindowOpaqueLocked(token, isOpaque);
4313         }
4314     }
4315
4316     public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
4317         AppWindowToken wtoken = findAppWindowToken(token);
4318         if (wtoken != null) {
4319             WindowState win = wtoken.findMainWindow();
4320             if (win != null) {
4321                 win.mWinAnimator.setOpaqueLocked(isOpaque);
4322             }
4323         }
4324     }
4325
4326     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4327             boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
4328         boolean delayed = false;
4329
4330         if (wtoken.clientHidden == visible) {
4331             wtoken.clientHidden = !visible;
4332             wtoken.sendAppVisibilityToClients();
4333         }
4334
4335         // Allow for state changes and animation to be applied if:
4336         // * token is transitioning visibility state
4337         // * or the token was marked as hidden and is exiting before we had a chance to play the
4338         // transition animation
4339         // * or this is an opening app and windows are being replaced.
4340         boolean visibilityChanged = false;
4341         if (wtoken.hidden == visible || (wtoken.hidden && wtoken.mIsExiting) ||
4342                 (visible && wtoken.waitingForReplacement())) {
4343             boolean changed = false;
4344             if (DEBUG_APP_TRANSITIONS) Slog.v(
4345                 TAG_WM, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4346                 + " performLayout=" + performLayout);
4347
4348             boolean runningAppAnimation = false;
4349
4350             if (transit != AppTransition.TRANSIT_UNSET) {
4351                 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4352                     wtoken.mAppAnimator.setNullAnimation();
4353                 }
4354                 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
4355                     delayed = runningAppAnimation = true;
4356                 }
4357                 WindowState window = wtoken.findMainWindow();
4358                 //TODO (multidisplay): Magnification is supported only for the default display.
4359                 if (window != null && mAccessibilityController != null
4360                         && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4361                     mAccessibilityController.onAppWindowTransitionLocked(window, transit);
4362                 }
4363                 changed = true;
4364             }
4365
4366             final int windowsCount = wtoken.allAppWindows.size();
4367             for (int i = 0; i < windowsCount; i++) {
4368                 WindowState win = wtoken.allAppWindows.get(i);
4369                 if (win == wtoken.startingWindow) {
4370                     // Starting window that's exiting will be removed when the animation
4371                     // finishes. Mark all relevant flags for that finishExit will proceed
4372                     // all the way to actually remove it.
4373                     if (!visible && win.isVisibleNow() && wtoken.mAppAnimator.isAnimating()) {
4374                         win.mAnimatingExit = true;
4375                         win.mRemoveOnExit = true;
4376                         win.mWindowRemovalAllowed = true;
4377                     }
4378                     continue;
4379                 }
4380
4381                 //Slog.i(TAG_WM, "Window " + win + ": vis=" + win.isVisible());
4382                 //win.dump("  ");
4383                 if (visible) {
4384                     if (!win.isVisibleNow()) {
4385                         if (!runningAppAnimation) {
4386                             win.mWinAnimator.applyAnimationLocked(
4387                                     WindowManagerPolicy.TRANSIT_ENTER, true);
4388                             //TODO (multidisplay): Magnification is supported only for the default
4389                             if (mAccessibilityController != null
4390                                     && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4391                                 mAccessibilityController.onWindowTransitionLocked(win,
4392                                         WindowManagerPolicy.TRANSIT_ENTER);
4393                             }
4394                         }
4395                         changed = true;
4396                         win.setDisplayLayoutNeeded();
4397                     }
4398                 } else if (win.isVisibleNow()) {
4399                     if (!runningAppAnimation) {
4400                         win.mWinAnimator.applyAnimationLocked(
4401                                 WindowManagerPolicy.TRANSIT_EXIT, false);
4402                         //TODO (multidisplay): Magnification is supported only for the default
4403                         if (mAccessibilityController != null
4404                                 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4405                             mAccessibilityController.onWindowTransitionLocked(win,
4406                                     WindowManagerPolicy.TRANSIT_EXIT);
4407                         }
4408                     }
4409                     changed = true;
4410                     win.setDisplayLayoutNeeded();
4411                 }
4412             }
4413
4414             wtoken.hidden = wtoken.hiddenRequested = !visible;
4415             visibilityChanged = true;
4416             if (!visible) {
4417                 unsetAppFreezingScreenLocked(wtoken, true, true);
4418             } else {
4419                 // If we are being set visible, and the starting window is
4420                 // not yet displayed, then make sure it doesn't get displayed.
4421                 WindowState swin = wtoken.startingWindow;
4422                 if (swin != null && !swin.isDrawnLw()) {
4423                     swin.mPolicyVisibility = false;
4424                     swin.mPolicyVisibilityAfterAnim = false;
4425                  }
4426             }
4427
4428             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setTokenVisibilityLocked: " + wtoken
4429                       + ": hidden=" + wtoken.hidden + " hiddenRequested="
4430                       + wtoken.hiddenRequested);
4431
4432             if (changed) {
4433                 mInputMonitor.setUpdateInputWindowsNeededLw();
4434                 if (performLayout) {
4435                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4436                             false /*updateInputWindows*/);
4437                     mWindowPlacerLocked.performSurfacePlacement();
4438                 }
4439                 mInputMonitor.updateInputWindowsLw(false /*force*/);
4440             }
4441         }
4442
4443         if (wtoken.mAppAnimator.animation != null) {
4444             delayed = true;
4445         }
4446
4447         for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4448             if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimationSet()) {
4449                 delayed = true;
4450             }
4451         }
4452
4453         if (visibilityChanged) {
4454             if (visible && !delayed) {
4455                 // The token was made immediately visible, there will be no entrance animation.
4456                 // We need to inform the client the enter animation was finished.
4457                 wtoken.mEnteringAnimation = true;
4458                 mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token);
4459             }
4460
4461             if (!mClosingApps.contains(wtoken) && !mOpeningApps.contains(wtoken)) {
4462                 // The token is not closing nor opening, so even if there is an animation set, that
4463                 // doesn't mean that it goes through the normal app transition cycle so we have
4464                 // to inform the docked controller about visibility change.
4465                 getDefaultDisplayContentLocked().getDockedDividerController()
4466                         .notifyAppVisibilityChanged();
4467             }
4468         }
4469
4470         return delayed;
4471     }
4472
4473     void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
4474         if (transit != AppTransition.TRANSIT_UNSET) {
4475             if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4476                 wtoken.mAppAnimator.setNullAnimation();
4477             }
4478             applyAnimationLocked(wtoken, null, transit, false, false);
4479         }
4480     }
4481
4482     @Override
4483     public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) {
4484         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4485                 "notifyAppResumed()")) {
4486             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4487         }
4488
4489         synchronized(mWindowMap) {
4490             final AppWindowToken wtoken;
4491             wtoken = findAppWindowToken(token);
4492             if (wtoken == null) {
4493                 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
4494                 return;
4495             }
4496             wtoken.notifyAppResumed(wasStopped, allowSavedSurface);
4497         }
4498     }
4499
4500     @Override
4501     public void notifyAppStopped(IBinder token) {
4502         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4503                 "notifyAppStopped()")) {
4504             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4505         }
4506
4507         synchronized(mWindowMap) {
4508             final AppWindowToken wtoken;
4509             wtoken = findAppWindowToken(token);
4510             if (wtoken == null) {
4511                 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
4512                 return;
4513             }
4514             wtoken.notifyAppStopped();
4515         }
4516     }
4517
4518     @Override
4519     public void setAppVisibility(IBinder token, boolean visible) {
4520         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4521                 "setAppVisibility()")) {
4522             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4523         }
4524
4525         AppWindowToken wtoken;
4526
4527         synchronized(mWindowMap) {
4528             wtoken = findAppWindowToken(token);
4529             if (wtoken == null) {
4530                 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
4531                 return;
4532             }
4533
4534             if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility(" +
4535                     token + ", visible=" + visible + "): " + mAppTransition +
4536                     " hidden=" + wtoken.hidden + " hiddenRequested=" +
4537                     wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
4538
4539             mOpeningApps.remove(wtoken);
4540             mClosingApps.remove(wtoken);
4541             wtoken.waitingToShow = false;
4542             wtoken.hiddenRequested = !visible;
4543
4544             if (!visible) {
4545                 // If the app is dead while it was visible, we kept its dead window on screen.
4546                 // Now that the app is going invisible, we can remove it. It will be restarted
4547                 // if made visible again.
4548                 wtoken.removeAllDeadWindows();
4549                 wtoken.setVisibleBeforeClientHidden();
4550             } else if (visible) {
4551                 if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
4552                     // Add the app mOpeningApps if transition is unset but ready. This means
4553                     // we're doing a screen freeze, and the unfreeze will wait for all opening
4554                     // apps to be ready.
4555                     mOpeningApps.add(wtoken);
4556                 }
4557                 wtoken.startingMoved = false;
4558                 // If the token is currently hidden (should be the common case), or has been
4559                 // stopped, then we need to set up to wait for its windows to be ready.
4560                 if (wtoken.hidden || wtoken.mAppStopped) {
4561                     wtoken.clearAllDrawn();
4562
4563                     // If the app was already visible, don't reset the waitingToShow state.
4564                     if (wtoken.hidden) {
4565                         wtoken.waitingToShow = true;
4566                     }
4567
4568                     if (wtoken.clientHidden) {
4569                         // In the case where we are making an app visible
4570                         // but holding off for a transition, we still need
4571                         // to tell the client to make its windows visible so
4572                         // they get drawn.  Otherwise, we will wait on
4573                         // performing the transition until all windows have
4574                         // been drawn, they never will be, and we are sad.
4575                         wtoken.clientHidden = false;
4576                         wtoken.sendAppVisibilityToClients();
4577                     }
4578                 }
4579                 wtoken.requestUpdateWallpaperIfNeeded();
4580
4581                 if (DEBUG_ADD_REMOVE) Slog.v(
4582                         TAG_WM, "No longer Stopped: " + wtoken);
4583                 wtoken.mAppStopped = false;
4584             }
4585
4586             // If we are preparing an app transition, then delay changing
4587             // the visibility of this token until we execute that transition.
4588             if (okToDisplay() && mAppTransition.isTransitionSet()) {
4589                 // A dummy animation is a placeholder animation which informs others that an
4590                 // animation is going on (in this case an application transition). If the animation
4591                 // was transferred from another application/animator, no dummy animator should be
4592                 // created since an animation is already in progress.
4593                 if (wtoken.mAppAnimator.usingTransferredAnimation
4594                         && wtoken.mAppAnimator.animation == null) {
4595                     Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
4596                             + ", using null transfered animation!");
4597                 }
4598                 if (!wtoken.mAppAnimator.usingTransferredAnimation &&
4599                         (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
4600                     if (DEBUG_APP_TRANSITIONS) Slog.v(
4601                             TAG_WM, "Setting dummy animation on: " + wtoken);
4602                     wtoken.mAppAnimator.setDummyAnimation();
4603                 }
4604                 wtoken.inPendingTransaction = true;
4605                 if (visible) {
4606                     mOpeningApps.add(wtoken);
4607                     wtoken.mEnteringAnimation = true;
4608                 } else {
4609                     mClosingApps.add(wtoken);
4610                     wtoken.mEnteringAnimation = false;
4611                 }
4612                 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
4613                     // We're launchingBehind, add the launching activity to mOpeningApps.
4614                     final WindowState win =
4615                             findFocusedWindowLocked(getDefaultDisplayContentLocked());
4616                     if (win != null) {
4617                         final AppWindowToken focusedToken = win.mAppToken;
4618                         if (focusedToken != null) {
4619                             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, " +
4620                                     " adding " + focusedToken + " to mOpeningApps");
4621                             // Force animation to be loaded.
4622                             focusedToken.hidden = true;
4623                             mOpeningApps.add(focusedToken);
4624                         }
4625                     }
4626                 }
4627                 return;
4628             }
4629
4630             final long origId = Binder.clearCallingIdentity();
4631             wtoken.inPendingTransaction = false;
4632             setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4633                     true, wtoken.voiceInteraction);
4634             wtoken.updateReportedVisibilityLocked();
4635             Binder.restoreCallingIdentity(origId);
4636         }
4637     }
4638
4639     void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4640             boolean unfreezeSurfaceNow, boolean force) {
4641         if (wtoken.mAppAnimator.freezingScreen) {
4642             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + wtoken
4643                     + " force=" + force);
4644             final int N = wtoken.allAppWindows.size();
4645             boolean unfrozeWindows = false;
4646             for (int i=0; i<N; i++) {
4647                 WindowState w = wtoken.allAppWindows.get(i);
4648                 if (w.mAppFreezing) {
4649                     w.mAppFreezing = false;
4650                     if (w.mHasSurface && !w.mOrientationChanging
4651                             && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
4652                         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + w);
4653                         w.mOrientationChanging = true;
4654                         mWindowPlacerLocked.mOrientationChangeComplete = false;
4655                     }
4656                     w.mLastFreezeDuration = 0;
4657                     unfrozeWindows = true;
4658                     w.setDisplayLayoutNeeded();
4659                 }
4660             }
4661             if (force || unfrozeWindows) {
4662                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + wtoken);
4663                 wtoken.mAppAnimator.freezingScreen = false;
4664                 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4665                         - mDisplayFreezeTime);
4666                 mAppsFreezingScreen--;
4667                 mLastFinishedFreezeSource = wtoken;
4668             }
4669             if (unfreezeSurfaceNow) {
4670                 if (unfrozeWindows) {
4671                     mWindowPlacerLocked.performSurfacePlacement();
4672                 }
4673                 stopFreezingDisplayLocked();
4674             }
4675         }
4676     }
4677
4678     private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4679         if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + wtoken.appToken + ": hidden="
4680                 + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4681         if (!wtoken.hiddenRequested) {
4682             if (!wtoken.mAppAnimator.freezingScreen) {
4683                 wtoken.mAppAnimator.freezingScreen = true;
4684                 wtoken.mAppAnimator.lastFreezeDuration = 0;
4685                 mAppsFreezingScreen++;
4686                 if (mAppsFreezingScreen == 1) {
4687                     startFreezingDisplayLocked(false, 0, 0);
4688                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4689                     mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
4690                 }
4691             }
4692             final int N = wtoken.allAppWindows.size();
4693             for (int i=0; i<N; i++) {
4694                 WindowState w = wtoken.allAppWindows.get(i);
4695                 w.mAppFreezing = true;
4696             }
4697         }
4698     }
4699
4700     @Override
4701     public void startAppFreezingScreen(IBinder token, int configChanges) {
4702         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4703                 "setAppFreezingScreen()")) {
4704             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4705         }
4706
4707         synchronized(mWindowMap) {
4708             if (configChanges == 0 && okToDisplay()) {
4709                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + token);
4710                 return;
4711             }
4712
4713             AppWindowToken wtoken = findAppWindowToken(token);
4714             if (wtoken == null || wtoken.appToken == null) {
4715                 Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + wtoken);
4716                 return;
4717             }
4718             final long origId = Binder.clearCallingIdentity();
4719             startAppFreezingScreenLocked(wtoken);
4720             Binder.restoreCallingIdentity(origId);
4721         }
4722     }
4723
4724     @Override
4725     public void stopAppFreezingScreen(IBinder token, boolean force) {
4726         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4727                 "setAppFreezingScreen()")) {
4728             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4729         }
4730
4731         synchronized(mWindowMap) {
4732             AppWindowToken wtoken = findAppWindowToken(token);
4733             if (wtoken == null || wtoken.appToken == null) {
4734                 return;
4735             }
4736             final long origId = Binder.clearCallingIdentity();
4737             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token
4738                     + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4739             unsetAppFreezingScreenLocked(wtoken, true, force);
4740             Binder.restoreCallingIdentity(origId);
4741         }
4742     }
4743
4744     @Override
4745     public void removeAppToken(IBinder token) {
4746         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4747                 "removeAppToken()")) {
4748             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4749         }
4750
4751         AppWindowToken wtoken = null;
4752         AppWindowToken startingToken = null;
4753         boolean delayed = false;
4754
4755         final long origId = Binder.clearCallingIdentity();
4756         synchronized(mWindowMap) {
4757             WindowToken basewtoken = mTokenMap.remove(token);
4758             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4759                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + wtoken);
4760                 delayed = setTokenVisibilityLocked(wtoken, null, false,
4761                         AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction);
4762                 wtoken.inPendingTransaction = false;
4763                 mOpeningApps.remove(wtoken);
4764                 wtoken.waitingToShow = false;
4765                 if (mClosingApps.contains(wtoken)) {
4766                     delayed = true;
4767                 } else if (mAppTransition.isTransitionSet()) {
4768                     mClosingApps.add(wtoken);
4769                     delayed = true;
4770                 }
4771                 if (DEBUG_APP_TRANSITIONS) Slog.v(
4772                         TAG_WM, "Removing app " + wtoken + " delayed=" + delayed
4773                         + " animation=" + wtoken.mAppAnimator.animation
4774                         + " animating=" + wtoken.mAppAnimator.animating);
4775                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
4776                         + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4777                 final TaskStack stack = wtoken.mTask.mStack;
4778                 if (delayed && !wtoken.allAppWindows.isEmpty()) {
4779                     // set the token aside because it has an active animation to be finished
4780                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
4781                             "removeAppToken make exiting: " + wtoken);
4782                     stack.mExitingAppTokens.add(wtoken);
4783                     wtoken.mIsExiting = true;
4784                 } else {
4785                     // Make sure there is no animation running on this token,
4786                     // so any windows associated with it will be removed as
4787                     // soon as their animations are complete
4788                     wtoken.mAppAnimator.clearAnimation();
4789                     wtoken.mAppAnimator.animating = false;
4790                     wtoken.removeAppFromTaskLocked();
4791                 }
4792
4793                 wtoken.removed = true;
4794                 if (wtoken.startingData != null) {
4795                     startingToken = wtoken;
4796                 }
4797                 unsetAppFreezingScreenLocked(wtoken, true, true);
4798                 if (mFocusedApp == wtoken) {
4799                     if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + wtoken);
4800                     mFocusedApp = null;
4801                     updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4802                     mInputMonitor.setFocusedAppLw(null);
4803                 }
4804             } else {
4805                 Slog.w(TAG_WM, "Attempted to remove non-existing app token: " + token);
4806             }
4807
4808             if (!delayed && wtoken != null) {
4809                 wtoken.updateReportedVisibilityLocked();
4810             }
4811
4812             // Will only remove if startingToken non null.
4813             scheduleRemoveStartingWindowLocked(startingToken);
4814         }
4815         Binder.restoreCallingIdentity(origId);
4816
4817     }
4818
4819     void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
4820         if (wtoken == null) {
4821             return;
4822         }
4823         if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) {
4824             // Already scheduled.
4825             return;
4826         }
4827
4828         if (wtoken.startingWindow == null) {
4829             if (wtoken.startingData != null) {
4830                 // Starting window has not been added yet, but it is scheduled to be added.
4831                 // Go ahead and cancel the request.
4832                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
4833                         "Clearing startingData for token=" + wtoken);
4834                 wtoken.startingData = null;
4835             }
4836             return;
4837         }
4838
4839         if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
4840                 ": Schedule remove starting " + wtoken + (wtoken != null ?
4841                 " startingWindow=" + wtoken.startingWindow : ""));
4842         Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4843         mH.sendMessage(m);
4844     }
4845
4846     void dumpAppTokensLocked() {
4847         final int numStacks = mStackIdToStack.size();
4848         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4849             final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4850             Slog.v(TAG_WM, "  Stack #" + stack.mStackId + " tasks from bottom to top:");
4851             final ArrayList<Task> tasks = stack.getTasks();
4852             final int numTasks = tasks.size();
4853             for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4854                 final Task task = tasks.get(taskNdx);
4855                 Slog.v(TAG_WM, "    Task #" + task.mTaskId + " activities from bottom to top:");
4856                 AppTokenList tokens = task.mAppTokens;
4857                 final int numTokens = tokens.size();
4858                 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4859                     Slog.v(TAG_WM, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4860                 }
4861             }
4862         }
4863     }
4864
4865     void dumpWindowsLocked() {
4866         final int numDisplays = mDisplayContents.size();
4867         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4868             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4869             Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId());
4870             final WindowList windows = displayContent.getWindowList();
4871             for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4872                 Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
4873             }
4874         }
4875     }
4876
4877     private final int reAddWindowLocked(int index, WindowState win) {
4878         final WindowList windows = win.getWindowList();
4879         // Adding child windows relies on mChildWindows being ordered by mSubLayer.
4880         final int NCW = win.mChildWindows.size();
4881         boolean winAdded = false;
4882         for (int j=0; j<NCW; j++) {
4883             WindowState cwin = win.mChildWindows.get(j);
4884             if (!winAdded && cwin.mSubLayer >= 0) {
4885                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding child window at "
4886                         + index + ": " + cwin);
4887                 win.mRebuilding = false;
4888                 windows.add(index, win);
4889                 index++;
4890                 winAdded = true;
4891             }
4892             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at "
4893                     + index + ": " + cwin);
4894             cwin.mRebuilding = false;
4895             windows.add(index, cwin);
4896             index++;
4897         }
4898         if (!winAdded) {
4899             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at "
4900                     + index + ": " + win);
4901             win.mRebuilding = false;
4902             windows.add(index, win);
4903             index++;
4904         }
4905         mWindowsChanged = true;
4906         return index;
4907     }
4908
4909     private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4910                                             WindowToken token) {
4911         final int NW = token.windows.size();
4912         for (int i=0; i<NW; i++) {
4913             final WindowState win = token.windows.get(i);
4914             final DisplayContent winDisplayContent = win.getDisplayContent();
4915             if (winDisplayContent == displayContent || winDisplayContent == null) {
4916                 win.mDisplayContent = displayContent;
4917                 index = reAddWindowLocked(index, win);
4918             }
4919         }
4920         return index;
4921     }
4922
4923
4924     void moveStackWindowsLocked(DisplayContent displayContent) {
4925         final WindowList windows = displayContent.getWindowList();
4926         mTmpWindows.addAll(windows);
4927
4928         rebuildAppWindowListLocked(displayContent);
4929
4930         // Set displayContent.layoutNeeded if window order changed.
4931         final int tmpSize = mTmpWindows.size();
4932         final int winSize = windows.size();
4933         int tmpNdx = 0, winNdx = 0;
4934         while (tmpNdx < tmpSize && winNdx < winSize) {
4935             // Skip over all exiting windows, they've been moved out of order.
4936             WindowState tmp;
4937             do {
4938                 tmp = mTmpWindows.get(tmpNdx++);
4939             } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
4940
4941             WindowState win;
4942             do {
4943                 win = windows.get(winNdx++);
4944             } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
4945
4946             if (tmp != win) {
4947                 // Window order changed.
4948                 displayContent.layoutNeeded = true;
4949                 break;
4950             }
4951         }
4952         if (tmpNdx != winNdx) {
4953             // One list was different from the other.
4954             displayContent.layoutNeeded = true;
4955         }
4956         mTmpWindows.clear();
4957
4958         if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4959                 false /*updateInputWindows*/)) {
4960             mLayersController.assignLayersLocked(displayContent.getWindowList());
4961         }
4962
4963         mInputMonitor.setUpdateInputWindowsNeededLw();
4964         mWindowPlacerLocked.performSurfacePlacement();
4965         mInputMonitor.updateInputWindowsLw(false /*force*/);
4966         //dump();
4967     }
4968
4969     public void moveTaskToTop(int taskId) {
4970         final long origId = Binder.clearCallingIdentity();
4971         try {
4972             synchronized(mWindowMap) {
4973                 Task task = mTaskIdToTask.get(taskId);
4974                 if (task == null) {
4975                     // Normal behavior, addAppToken will be called next and task will be created.
4976                     return;
4977                 }
4978                 final TaskStack stack = task.mStack;
4979                 final DisplayContent displayContent = task.getDisplayContent();
4980                 displayContent.moveStack(stack, true);
4981                 if (displayContent.isDefaultDisplay) {
4982                     final TaskStack homeStack = displayContent.getHomeStack();
4983                     if (homeStack != stack) {
4984                         // When a non-home stack moves to the top, the home stack moves to the
4985                         // bottom.
4986                         displayContent.moveStack(homeStack, false);
4987                     }
4988                 }
4989                 stack.moveTaskToTop(task);
4990                 if (mAppTransition.isTransitionSet()) {
4991                     task.setSendingToBottom(false);
4992                 }
4993                 moveStackWindowsLocked(displayContent);
4994             }
4995         } finally {
4996             Binder.restoreCallingIdentity(origId);
4997         }
4998     }
4999
5000     public void moveTaskToBottom(int taskId) {
5001         final long origId = Binder.clearCallingIdentity();
5002         try {
5003             synchronized(mWindowMap) {
5004                 Task task = mTaskIdToTask.get(taskId);
5005                 if (task == null) {
5006                     Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + taskId
5007                             + " not found in mTaskIdToTask");
5008                     return;
5009                 }
5010                 final TaskStack stack = task.mStack;
5011                 stack.moveTaskToBottom(task);
5012                 if (mAppTransition.isTransitionSet()) {
5013                     task.setSendingToBottom(true);
5014                 }
5015                 moveStackWindowsLocked(stack.getDisplayContent());
5016             }
5017         } finally {
5018             Binder.restoreCallingIdentity(origId);
5019         }
5020     }
5021
5022     boolean isStackVisibleLocked(int stackId) {
5023         final TaskStack stack = mStackIdToStack.get(stackId);
5024         return (stack != null && stack.isVisibleLocked());
5025     }
5026
5027     public void setDockedStackCreateState(int mode, Rect bounds) {
5028         synchronized (mWindowMap) {
5029             setDockedStackCreateStateLocked(mode, bounds);
5030         }
5031     }
5032
5033     void setDockedStackCreateStateLocked(int mode, Rect bounds) {
5034         mDockedStackCreateMode = mode;
5035         mDockedStackCreateBounds = bounds;
5036     }
5037
5038     /**
5039      * Create a new TaskStack and place it on a DisplayContent.
5040      * @param stackId The unique identifier of the new stack.
5041      * @param displayId The unique identifier of the DisplayContent.
5042      * @param onTop If true the stack will be place at the top of the display,
5043      *              else at the bottom
5044      * @return The initial bounds the stack was created with. null means fullscreen.
5045      */
5046     public Rect attachStack(int stackId, int displayId, boolean onTop) {
5047         final long origId = Binder.clearCallingIdentity();
5048         try {
5049             synchronized (mWindowMap) {
5050                 final DisplayContent displayContent = mDisplayContents.get(displayId);
5051                 boolean attachedToDisplay = false;
5052                 if (displayContent != null) {
5053                     TaskStack stack = mStackIdToStack.get(stackId);
5054                     if (stack == null) {
5055                         if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
5056
5057                         stack = displayContent.getStackById(stackId);
5058                         if (stack != null) {
5059                             // It's already attached to the display. Detach and re-attach
5060                             // because onTop might change, and be sure to clear mDeferDetach!
5061                             displayContent.detachStack(stack);
5062                             stack.mDeferDetach = false;
5063                             attachedToDisplay = true;
5064                         } else {
5065                             stack = new TaskStack(this, stackId);
5066                         }
5067
5068                         mStackIdToStack.put(stackId, stack);
5069                         if (stackId == DOCKED_STACK_ID) {
5070                             getDefaultDisplayContentLocked().mDividerControllerLocked
5071                                     .notifyDockedStackExistsChanged(true);
5072                         }
5073                     }
5074                     if (!attachedToDisplay) {
5075                         stack.attachDisplayContent(displayContent);
5076                     }
5077                     displayContent.attachStack(stack, onTop);
5078                     if (stack.getRawFullscreen()) {
5079                         return null;
5080                     }
5081                     Rect bounds = new Rect();
5082                     stack.getRawBounds(bounds);
5083                     return bounds;
5084                 }
5085             }
5086         } finally {
5087             Binder.restoreCallingIdentity(origId);
5088         }
5089         return null;
5090     }
5091
5092     void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
5093         displayContent.detachStack(stack);
5094         stack.detachDisplay();
5095         if (stack.mStackId == DOCKED_STACK_ID) {
5096             getDefaultDisplayContentLocked().mDividerControllerLocked
5097                     .notifyDockedStackExistsChanged(false);
5098         }
5099     }
5100
5101     public void detachStack(int stackId) {
5102         synchronized (mWindowMap) {
5103             TaskStack stack = mStackIdToStack.get(stackId);
5104             if (stack != null) {
5105                 final DisplayContent displayContent = stack.getDisplayContent();
5106                 if (displayContent != null) {
5107                     if (stack.isAnimating()) {
5108                         stack.mDeferDetach = true;
5109                         return;
5110                     }
5111                     detachStackLocked(displayContent, stack);
5112                 }
5113             }
5114         }
5115     }
5116
5117     public void removeStack(int stackId) {
5118         synchronized (mWindowMap) {
5119             mStackIdToStack.remove(stackId);
5120         }
5121     }
5122
5123     public void removeTask(int taskId) {
5124         synchronized (mWindowMap) {
5125             Task task = mTaskIdToTask.get(taskId);
5126             if (task == null) {
5127                 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId);
5128                 return;
5129             }
5130             task.removeLocked();
5131         }
5132     }
5133
5134     @Override
5135     public void cancelTaskWindowTransition(int taskId) {
5136         synchronized (mWindowMap) {
5137             Task task = mTaskIdToTask.get(taskId);
5138             if (task != null) {
5139                 task.cancelTaskWindowTransition();
5140             }
5141         }
5142     }
5143
5144     @Override
5145     public void cancelTaskThumbnailTransition(int taskId) {
5146         synchronized (mWindowMap) {
5147             Task task = mTaskIdToTask.get(taskId);
5148             if (task != null) {
5149                 task.cancelTaskThumbnailTransition();
5150             }
5151         }
5152     }
5153
5154     public void addTask(int taskId, int stackId, boolean toTop) {
5155         synchronized (mWindowMap) {
5156             if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: adding taskId=" + taskId
5157                     + " to " + (toTop ? "top" : "bottom"));
5158             Task task = mTaskIdToTask.get(taskId);
5159             if (task == null) {
5160                 if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: could not find taskId=" + taskId);
5161                 return;
5162             }
5163             TaskStack stack = mStackIdToStack.get(stackId);
5164             stack.addTask(task, toTop);
5165             final DisplayContent displayContent = stack.getDisplayContent();
5166             displayContent.layoutNeeded = true;
5167             mWindowPlacerLocked.performSurfacePlacement();
5168         }
5169     }
5170
5171     public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
5172         synchronized (mWindowMap) {
5173             if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: moving taskId=" + taskId
5174                     + " to stackId=" + stackId + " at " + (toTop ? "top" : "bottom"));
5175             Task task = mTaskIdToTask.get(taskId);
5176             if (task == null) {
5177                 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find taskId=" + taskId);
5178                 return;
5179             }
5180             TaskStack stack = mStackIdToStack.get(stackId);
5181             if (stack == null) {
5182                 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find stackId=" + stackId);
5183                 return;
5184             }
5185             task.moveTaskToStack(stack, toTop);
5186             final DisplayContent displayContent = stack.getDisplayContent();
5187             displayContent.layoutNeeded = true;
5188             mWindowPlacerLocked.performSurfacePlacement();
5189         }
5190     }
5191
5192     public void getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility) {
5193         synchronized (mWindowMap) {
5194             final TaskStack stack = mStackIdToStack.get(stackId);
5195             if (stack != null) {
5196                 stack.getStackDockedModeBoundsLocked(bounds, ignoreVisibility);
5197                 return;
5198             }
5199             bounds.setEmpty();
5200         }
5201     }
5202
5203     @Override
5204     public void getStackBounds(int stackId, Rect bounds) {
5205         synchronized (mWindowMap) {
5206             final TaskStack stack = mStackIdToStack.get(stackId);
5207             if (stack != null) {
5208                 stack.getBounds(bounds);
5209                 return;
5210             }
5211             bounds.setEmpty();
5212         }
5213     }
5214
5215     /**
5216      * Re-sizes a stack and its containing tasks.
5217      * @param stackId Id of stack to resize.
5218      * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
5219      * @param configs Configurations for tasks in the resized stack, keyed by task id.
5220      * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
5221      * @return True if the stack is now fullscreen.
5222      * */
5223     public boolean resizeStack(int stackId, Rect bounds,
5224             SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
5225             SparseArray<Rect> taskTempInsetBounds) {
5226         synchronized (mWindowMap) {
5227             final TaskStack stack = mStackIdToStack.get(stackId);
5228             if (stack == null) {
5229                 throw new IllegalArgumentException("resizeStack: stackId " + stackId
5230                         + " not found.");
5231             }
5232             if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
5233                     && stack.isVisibleLocked()) {
5234                 stack.getDisplayContent().layoutNeeded = true;
5235                 mWindowPlacerLocked.performSurfacePlacement();
5236             }
5237             return stack.getRawFullscreen();
5238         }
5239     }
5240
5241     public void prepareFreezingTaskBounds(int stackId) {
5242         synchronized (mWindowMap) {
5243             final TaskStack stack = mStackIdToStack.get(stackId);
5244             if (stack == null) {
5245                 throw new IllegalArgumentException("prepareFreezingTaskBounds: stackId " + stackId
5246                         + " not found.");
5247             }
5248             stack.prepareFreezingTaskBounds();
5249         }
5250     }
5251
5252     public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds,
5253             Configuration config) {
5254         synchronized (mWindowMap) {
5255             if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: positioning taskId=" + taskId
5256                     + " in stackId=" + stackId + " at " + position);
5257             Task task = mTaskIdToTask.get(taskId);
5258             if (task == null) {
5259                 if (DEBUG_STACK) Slog.i(TAG_WM,
5260                         "positionTaskInStack: could not find taskId=" + taskId);
5261                 return;
5262             }
5263             TaskStack stack = mStackIdToStack.get(stackId);
5264             if (stack == null) {
5265                 if (DEBUG_STACK) Slog.i(TAG_WM,
5266                         "positionTaskInStack: could not find stackId=" + stackId);
5267                 return;
5268             }
5269             task.positionTaskInStack(stack, position, bounds, config);
5270             final DisplayContent displayContent = stack.getDisplayContent();
5271             displayContent.layoutNeeded = true;
5272             mWindowPlacerLocked.performSurfacePlacement();
5273         }
5274     }
5275
5276     /**
5277      * Re-sizes the specified task and its containing windows.
5278      * Returns a {@link Configuration} object that contains configurations settings
5279      * that should be overridden due to the operation.
5280      */
5281     public void resizeTask(int taskId, Rect bounds, Configuration configuration,
5282             boolean relayout, boolean forced) {
5283         synchronized (mWindowMap) {
5284             Task task = mTaskIdToTask.get(taskId);
5285             if (task == null) {
5286                 throw new IllegalArgumentException("resizeTask: taskId " + taskId
5287                         + " not found.");
5288             }
5289
5290             if (task.resizeLocked(bounds, configuration, forced) && relayout) {
5291                 task.getDisplayContent().layoutNeeded = true;
5292                 mWindowPlacerLocked.performSurfacePlacement();
5293             }
5294         }
5295     }
5296
5297     /**
5298      * Puts a specific task into docked drag resizing mode. See {@link DragResizeMode}.
5299      *
5300      * @param taskId The id of the task to put into drag resize mode.
5301      * @param resizing Whether to put the task into drag resize mode.
5302      */
5303     public void setTaskDockedResizing(int taskId, boolean resizing) {
5304         synchronized (mWindowMap) {
5305             Task task = mTaskIdToTask.get(taskId);
5306             if (task == null) {
5307                 Slog.w(TAG, "setTaskDockedResizing: taskId " + taskId + " not found.");
5308                 return;
5309             }
5310             task.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
5311         }
5312     }
5313
5314     public void scrollTask(int taskId, Rect bounds) {
5315         synchronized (mWindowMap) {
5316             Task task = mTaskIdToTask.get(taskId);
5317             if (task == null) {
5318                 throw new IllegalArgumentException("scrollTask: taskId " + taskId
5319                         + " not found.");
5320             }
5321
5322             if (task.scrollLocked(bounds)) {
5323                 task.getDisplayContent().layoutNeeded = true;
5324                 mInputMonitor.setUpdateInputWindowsNeededLw();
5325                 mWindowPlacerLocked.performSurfacePlacement();
5326             }
5327         }
5328     }
5329     /**
5330      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
5331      * performance, only one layout pass should be done. This can be called multiple times, and
5332      * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
5333      */
5334     public void deferSurfaceLayout() {
5335         synchronized (mWindowMap) {
5336             mWindowPlacerLocked.deferLayout();
5337         }
5338     }
5339
5340     /**
5341      * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
5342      */
5343     public void continueSurfaceLayout() {
5344         synchronized (mWindowMap) {
5345             mWindowPlacerLocked.continueLayout();
5346         }
5347     }
5348
5349     public void getTaskBounds(int taskId, Rect bounds) {
5350         synchronized (mWindowMap) {
5351             Task task = mTaskIdToTask.get(taskId);
5352             if (task != null) {
5353                 task.getBounds(bounds);
5354                 return;
5355             }
5356             bounds.setEmpty();
5357         }
5358     }
5359
5360     /** Return true if the input task id represents a valid window manager task. */
5361     public boolean isValidTaskId(int taskId) {
5362         synchronized (mWindowMap) {
5363             return mTaskIdToTask.get(taskId) != null;
5364         }
5365     }
5366
5367     // -------------------------------------------------------------
5368     // Misc IWindowSession methods
5369     // -------------------------------------------------------------
5370
5371     @Override
5372     public void startFreezingScreen(int exitAnim, int enterAnim) {
5373         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5374                 "startFreezingScreen()")) {
5375             throw new SecurityException("Requires FREEZE_SCREEN permission");
5376         }
5377
5378         synchronized(mWindowMap) {
5379             if (!mClientFreezingScreen) {
5380                 mClientFreezingScreen = true;
5381                 final long origId = Binder.clearCallingIdentity();
5382                 try {
5383                     startFreezingDisplayLocked(false, exitAnim, enterAnim);
5384                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5385                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5386                 } finally {
5387                     Binder.restoreCallingIdentity(origId);
5388                 }
5389             }
5390         }
5391     }
5392
5393     @Override
5394     public void stopFreezingScreen() {
5395         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5396                 "stopFreezingScreen()")) {
5397             throw new SecurityException("Requires FREEZE_SCREEN permission");
5398         }
5399
5400         synchronized(mWindowMap) {
5401             if (mClientFreezingScreen) {
5402                 mClientFreezingScreen = false;
5403                 mLastFinishedFreezeSource = "client";
5404                 final long origId = Binder.clearCallingIdentity();
5405                 try {
5406                     stopFreezingDisplayLocked();
5407                 } finally {
5408                     Binder.restoreCallingIdentity(origId);
5409                 }
5410             }
5411         }
5412     }
5413
5414     @Override
5415     public void disableKeyguard(IBinder token, String tag) {
5416         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5417             != PackageManager.PERMISSION_GRANTED) {
5418             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5419         }
5420         // If this isn't coming from the system then don't allow disabling the lockscreen
5421         // to bypass security.
5422         if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) {
5423             Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
5424             return;
5425         }
5426
5427         // If this isn't coming from the current user, ignore it.
5428         if (Binder.getCallingUserHandle().getIdentifier() != mCurrentUserId) {
5429             Log.d(TAG_WM, "non-current user, ignore disableKeyguard");
5430             return;
5431         }
5432
5433         if (token == null) {
5434             throw new IllegalArgumentException("token == null");
5435         }
5436
5437         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5438                 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5439     }
5440
5441     @Override
5442     public void reenableKeyguard(IBinder token) {
5443         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5444             != PackageManager.PERMISSION_GRANTED) {
5445             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5446         }
5447
5448         if (token == null) {
5449             throw new IllegalArgumentException("token == null");
5450         }
5451
5452         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5453                 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5454     }
5455
5456     /**
5457      * @see android.app.KeyguardManager#exitKeyguardSecurely
5458      */
5459     @Override
5460     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5461         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5462             != PackageManager.PERMISSION_GRANTED) {
5463             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5464         }
5465
5466         if (callback == null) {
5467             throw new IllegalArgumentException("callback == null");
5468         }
5469
5470         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5471             @Override
5472             public void onKeyguardExitResult(boolean success) {
5473                 try {
5474                     callback.onKeyguardExitResult(success);
5475                 } catch (RemoteException e) {
5476                     // Client has died, we don't care.
5477                 }
5478             }
5479         });
5480     }
5481
5482     @Override
5483     public boolean inKeyguardRestrictedInputMode() {
5484         return mPolicy.inKeyguardRestrictedKeyInputMode();
5485     }
5486
5487     @Override
5488     public boolean isKeyguardLocked() {
5489         return mPolicy.isKeyguardLocked();
5490     }
5491
5492     @Override
5493     public boolean isKeyguardSecure() {
5494         int userId = UserHandle.getCallingUserId();
5495         long origId = Binder.clearCallingIdentity();
5496         try {
5497             return mPolicy.isKeyguardSecure(userId);
5498         } finally {
5499             Binder.restoreCallingIdentity(origId);
5500         }
5501     }
5502
5503     @Override
5504     public void dismissKeyguard() {
5505         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5506                 != PackageManager.PERMISSION_GRANTED) {
5507             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5508         }
5509         synchronized(mWindowMap) {
5510             mPolicy.dismissKeyguardLw();
5511         }
5512     }
5513
5514     @Override
5515     public void keyguardGoingAway(int flags) {
5516         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5517                 != PackageManager.PERMISSION_GRANTED) {
5518             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5519         }
5520         if (DEBUG_KEYGUARD) Slog.d(TAG_WM,
5521                 "keyguardGoingAway: flags=0x" + Integer.toHexString(flags));
5522         synchronized (mWindowMap) {
5523             mAnimator.mKeyguardGoingAway = true;
5524             mAnimator.mKeyguardGoingAwayFlags = flags;
5525             mWindowPlacerLocked.requestTraversal();
5526         }
5527     }
5528
5529     public void keyguardWaitingForActivityDrawn() {
5530         if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardWaitingForActivityDrawn");
5531         synchronized (mWindowMap) {
5532             mKeyguardWaitingForActivityDrawn = true;
5533         }
5534     }
5535
5536     public void notifyActivityDrawnForKeyguard() {
5537         if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "notifyActivityDrawnForKeyguard: waiting="
5538                 + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5));
5539         synchronized (mWindowMap) {
5540             if (mKeyguardWaitingForActivityDrawn) {
5541                 mPolicy.notifyActivityDrawnForKeyguardLw();
5542                 mKeyguardWaitingForActivityDrawn = false;
5543             }
5544         }
5545     }
5546
5547     void showGlobalActions() {
5548         mPolicy.showGlobalActions();
5549     }
5550
5551     @Override
5552     public void closeSystemDialogs(String reason) {
5553         synchronized(mWindowMap) {
5554             final int numDisplays = mDisplayContents.size();
5555             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5556                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5557                 final int numWindows = windows.size();
5558                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5559                     final WindowState w = windows.get(winNdx);
5560                     if (w.mHasSurface) {
5561                         try {
5562                             w.mClient.closeSystemDialogs(reason);
5563                         } catch (RemoteException e) {
5564                         }
5565                     }
5566                 }
5567             }
5568         }
5569     }
5570
5571     static float fixScale(float scale) {
5572         if (scale < 0) scale = 0;
5573         else if (scale > 20) scale = 20;
5574         return Math.abs(scale);
5575     }
5576
5577     @Override
5578     public void setAnimationScale(int which, float scale) {
5579         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5580                 "setAnimationScale()")) {
5581             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5582         }
5583
5584         scale = fixScale(scale);
5585         switch (which) {
5586             case 0: mWindowAnimationScaleSetting = scale; break;
5587             case 1: mTransitionAnimationScaleSetting = scale; break;
5588             case 2: mAnimatorDurationScaleSetting = scale; break;
5589         }
5590
5591         // Persist setting
5592         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5593     }
5594
5595     @Override
5596     public void setAnimationScales(float[] scales) {
5597         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5598                 "setAnimationScale()")) {
5599             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5600         }
5601
5602         if (scales != null) {
5603             if (scales.length >= 1) {
5604                 mWindowAnimationScaleSetting = fixScale(scales[0]);
5605             }
5606             if (scales.length >= 2) {
5607                 mTransitionAnimationScaleSetting = fixScale(scales[1]);
5608             }
5609             if (scales.length >= 3) {
5610                 mAnimatorDurationScaleSetting = fixScale(scales[2]);
5611                 dispatchNewAnimatorScaleLocked(null);
5612             }
5613         }
5614
5615         // Persist setting
5616         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5617     }
5618
5619     private void setAnimatorDurationScale(float scale) {
5620         mAnimatorDurationScaleSetting = scale;
5621         ValueAnimator.setDurationScale(scale);
5622     }
5623
5624     public float getWindowAnimationScaleLocked() {
5625         return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5626     }
5627
5628     public float getTransitionAnimationScaleLocked() {
5629         return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5630     }
5631
5632     @Override
5633     public float getAnimationScale(int which) {
5634         switch (which) {
5635             case 0: return mWindowAnimationScaleSetting;
5636             case 1: return mTransitionAnimationScaleSetting;
5637             case 2: return mAnimatorDurationScaleSetting;
5638         }
5639         return 0;
5640     }
5641
5642     @Override
5643     public float[] getAnimationScales() {
5644         return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5645                 mAnimatorDurationScaleSetting };
5646     }
5647
5648     @Override
5649     public float getCurrentAnimatorScale() {
5650         synchronized(mWindowMap) {
5651             return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5652         }
5653     }
5654
5655     void dispatchNewAnimatorScaleLocked(Session session) {
5656         mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5657     }
5658
5659     @Override
5660     public void registerPointerEventListener(PointerEventListener listener) {
5661         mPointerEventDispatcher.registerInputEventListener(listener);
5662     }
5663
5664     @Override
5665     public void unregisterPointerEventListener(PointerEventListener listener) {
5666         mPointerEventDispatcher.unregisterInputEventListener(listener);
5667     }
5668
5669     // Called by window manager policy. Not exposed externally.
5670     @Override
5671     public int getLidState() {
5672         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5673                 InputManagerService.SW_LID);
5674         if (sw > 0) {
5675             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5676             return LID_CLOSED;
5677         } else if (sw == 0) {
5678             // Switch state: AKEY_STATE_UP.
5679             return LID_OPEN;
5680         } else {
5681             // Switch state: AKEY_STATE_UNKNOWN.
5682             return LID_ABSENT;
5683         }
5684     }
5685
5686     // Called by window manager policy. Not exposed externally.
5687     @Override
5688     public void lockDeviceNow() {
5689         lockNow(null);
5690     }
5691
5692     // Called by window manager policy. Not exposed externally.
5693     @Override
5694     public int getCameraLensCoverState() {
5695         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5696                 InputManagerService.SW_CAMERA_LENS_COVER);
5697         if (sw > 0) {
5698             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5699             return CAMERA_LENS_COVERED;
5700         } else if (sw == 0) {
5701             // Switch state: AKEY_STATE_UP.
5702             return CAMERA_LENS_UNCOVERED;
5703         } else {
5704             // Switch state: AKEY_STATE_UNKNOWN.
5705             return CAMERA_LENS_COVER_ABSENT;
5706         }
5707     }
5708
5709     // Called by window manager policy.  Not exposed externally.
5710     @Override
5711     public void switchInputMethod(boolean forwardDirection) {
5712         final InputMethodManagerInternal inputMethodManagerInternal =
5713                 LocalServices.getService(InputMethodManagerInternal.class);
5714         if (inputMethodManagerInternal != null) {
5715             inputMethodManagerInternal.switchInputMethod(forwardDirection);
5716         }
5717     }
5718
5719     // Called by window manager policy.  Not exposed externally.
5720     @Override
5721     public void shutdown(boolean confirm) {
5722         ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
5723     }
5724
5725     // Called by window manager policy.  Not exposed externally.
5726     @Override
5727     public void reboot(boolean confirm) {
5728         ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
5729     }
5730
5731     // Called by window manager policy.  Not exposed externally.
5732     @Override
5733     public void rebootSafeMode(boolean confirm) {
5734         ShutdownThread.rebootSafeMode(mContext, confirm);
5735     }
5736
5737     public void setCurrentProfileIds(final int[] currentProfileIds) {
5738         synchronized (mWindowMap) {
5739             mCurrentProfileIds = currentProfileIds;
5740         }
5741     }
5742
5743     public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5744         synchronized (mWindowMap) {
5745             mCurrentUserId = newUserId;
5746             mCurrentProfileIds = currentProfileIds;
5747             mAppTransition.setCurrentUser(newUserId);
5748             mPolicy.setCurrentUserLw(newUserId);
5749
5750             // If keyguard was disabled, re-enable it
5751             // TODO: Keep track of keyguardEnabled state per user and use here...
5752             // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
5753             mPolicy.enableKeyguard(true);
5754
5755             // Hide windows that should not be seen by the new user.
5756             final int numDisplays = mDisplayContents.size();
5757             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5758                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5759                 displayContent.switchUserStacks();
5760                 rebuildAppWindowListLocked(displayContent);
5761             }
5762             mWindowPlacerLocked.performSurfacePlacement();
5763
5764             // Notify whether the docked stack exists for the current user
5765             final DisplayContent displayContent = getDefaultDisplayContentLocked();
5766             displayContent.mDividerControllerLocked
5767                     .notifyDockedStackExistsChanged(hasDockedTasksForUser(newUserId));
5768
5769             // If the display is already prepared, update the density.
5770             // Otherwise, we'll update it when it's prepared.
5771             if (mDisplayReady) {
5772                 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
5773                 final int targetDensity = forcedDensity != 0 ? forcedDensity
5774                         : displayContent.mInitialDisplayDensity;
5775                 setForcedDisplayDensityLocked(displayContent, targetDensity);
5776             }
5777         }
5778     }
5779
5780     /**
5781      * Returns whether there is a docked task for the current user.
5782      */
5783     boolean hasDockedTasksForUser(int userId) {
5784         final TaskStack stack = mStackIdToStack.get(DOCKED_STACK_ID);
5785         if (stack == null) {
5786             return false;
5787         }
5788
5789         final ArrayList<Task> tasks = stack.getTasks();
5790         boolean hasUserTask = false;
5791         for (int i = tasks.size() - 1; i >= 0 && !hasUserTask; i--) {
5792             final Task task = tasks.get(i);
5793             hasUserTask = (task.mUserId == userId);
5794         }
5795         return hasUserTask;
5796     }
5797
5798     /* Called by WindowState */
5799     boolean isCurrentProfileLocked(int userId) {
5800         if (userId == mCurrentUserId) return true;
5801         for (int i = 0; i < mCurrentProfileIds.length; i++) {
5802             if (mCurrentProfileIds[i] == userId) return true;
5803         }
5804         return false;
5805     }
5806
5807     public void enableScreenAfterBoot() {
5808         synchronized(mWindowMap) {
5809             if (DEBUG_BOOT) {
5810                 RuntimeException here = new RuntimeException("here");
5811                 here.fillInStackTrace();
5812                 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5813                         + " mForceDisplayEnabled=" + mForceDisplayEnabled
5814                         + " mShowingBootMessages=" + mShowingBootMessages
5815                         + " mSystemBooted=" + mSystemBooted, here);
5816             }
5817             if (mSystemBooted) {
5818                 return;
5819             }
5820             mSystemBooted = true;
5821             hideBootMessagesLocked();
5822             // If the screen still doesn't come up after 30 seconds, give
5823             // up and turn it on.
5824             mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5825         }
5826
5827         mPolicy.systemBooted();
5828
5829         performEnableScreen();
5830     }
5831
5832     @Override
5833     public void enableScreenIfNeeded() {
5834         synchronized (mWindowMap) {
5835             enableScreenIfNeededLocked();
5836         }
5837     }
5838
5839     void enableScreenIfNeededLocked() {
5840         if (DEBUG_BOOT) {
5841             RuntimeException here = new RuntimeException("here");
5842             here.fillInStackTrace();
5843             Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5844                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
5845                     + " mShowingBootMessages=" + mShowingBootMessages
5846                     + " mSystemBooted=" + mSystemBooted, here);
5847         }
5848         if (mDisplayEnabled) {
5849             return;
5850         }
5851         if (!mSystemBooted && !mShowingBootMessages) {
5852             return;
5853         }
5854         mH.sendEmptyMessage(H.ENABLE_SCREEN);
5855     }
5856
5857     public void performBootTimeout() {
5858         synchronized(mWindowMap) {
5859             if (mDisplayEnabled) {
5860                 return;
5861             }
5862             Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
5863             mForceDisplayEnabled = true;
5864         }
5865         performEnableScreen();
5866     }
5867
5868     private boolean checkWaitingForWindowsLocked() {
5869
5870         boolean haveBootMsg = false;
5871         boolean haveApp = false;
5872         // if the wallpaper service is disabled on the device, we're never going to have
5873         // wallpaper, don't bother waiting for it
5874         boolean haveWallpaper = false;
5875         boolean wallpaperEnabled = mContext.getResources().getBoolean(
5876                 com.android.internal.R.bool.config_enableWallpaperService)
5877                 && !mOnlyCore;
5878         boolean haveKeyguard = true;
5879         // TODO(multidisplay): Expand to all displays?
5880         final WindowList windows = getDefaultWindowListLocked();
5881         final int N = windows.size();
5882         for (int i=0; i<N; i++) {
5883             WindowState w = windows.get(i);
5884             if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5885                 return true;
5886             }
5887             if (w.isDrawnLw()) {
5888                 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5889                     haveBootMsg = true;
5890                 } else if (w.mAttrs.type == TYPE_APPLICATION
5891                         || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
5892                     haveApp = true;
5893                 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5894                     haveWallpaper = true;
5895                 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5896                     haveKeyguard = mPolicy.isKeyguardDrawnLw();
5897                 }
5898             }
5899         }
5900
5901         if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5902             Slog.i(TAG_WM, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5903                     + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5904                     + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5905                     + " haveKeyguard=" + haveKeyguard);
5906         }
5907
5908         // If we are turning on the screen to show the boot message,
5909         // don't do it until the boot message is actually displayed.
5910         if (!mSystemBooted && !haveBootMsg) {
5911             return true;
5912         }
5913
5914         // If we are turning on the screen after the boot is completed
5915         // normally, don't do so until we have the application and
5916         // wallpaper.
5917         if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5918                 (wallpaperEnabled && !haveWallpaper))) {
5919             return true;
5920         }
5921
5922         return false;
5923     }
5924
5925     public void performEnableScreen() {
5926         synchronized(mWindowMap) {
5927             if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5928                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
5929                     + " mShowingBootMessages=" + mShowingBootMessages
5930                     + " mSystemBooted=" + mSystemBooted
5931                     + " mOnlyCore=" + mOnlyCore,
5932                     new RuntimeException("here").fillInStackTrace());
5933             if (mDisplayEnabled) {
5934                 return;
5935             }
5936             if (!mSystemBooted && !mShowingBootMessages) {
5937                 return;
5938             }
5939
5940             // Don't enable the screen until all existing windows have been drawn.
5941             if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
5942                 return;
5943             }
5944
5945             if (!mBootAnimationStopped) {
5946                 // Do this one time.
5947                 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
5948                 try {
5949                     IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5950                     if (surfaceFlinger != null) {
5951                         //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5952                         Parcel data = Parcel.obtain();
5953                         data.writeInterfaceToken("android.ui.ISurfaceComposer");
5954                         surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5955                                 data, null, 0);
5956                         data.recycle();
5957                     }
5958                 } catch (RemoteException ex) {
5959                     Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
5960                 }
5961                 mBootAnimationStopped = true;
5962             }
5963
5964             if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
5965                 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
5966                 return;
5967             }
5968
5969             EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
5970             Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
5971             mDisplayEnabled = true;
5972             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
5973
5974             // Enable input dispatch.
5975             mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5976         }
5977
5978         try {
5979             mActivityManager.bootAnimationComplete();
5980         } catch (RemoteException e) {
5981         }
5982
5983         mPolicy.enableScreenAfterBoot();
5984
5985         // Make sure the last requested orientation has been applied.
5986         updateRotationUnchecked(false, false);
5987     }
5988
5989     private boolean checkBootAnimationCompleteLocked() {
5990         if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
5991             mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
5992             mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
5993                     BOOT_ANIMATION_POLL_INTERVAL);
5994             if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
5995             return false;
5996         }
5997         if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
5998         return true;
5999     }
6000
6001     public void showBootMessage(final CharSequence msg, final boolean always) {
6002         boolean first = false;
6003         synchronized(mWindowMap) {
6004             if (DEBUG_BOOT) {
6005                 RuntimeException here = new RuntimeException("here");
6006                 here.fillInStackTrace();
6007                 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
6008                         + " mAllowBootMessages=" + mAllowBootMessages
6009                         + " mShowingBootMessages=" + mShowingBootMessages
6010                         + " mSystemBooted=" + mSystemBooted, here);
6011             }
6012             if (!mAllowBootMessages) {
6013                 return;
6014             }
6015             if (!mShowingBootMessages) {
6016                 if (!always) {
6017                     return;
6018                 }
6019                 first = true;
6020             }
6021             if (mSystemBooted) {
6022                 return;
6023             }
6024             mShowingBootMessages = true;
6025             mPolicy.showBootMessage(msg, always);
6026         }
6027         if (first) {
6028             performEnableScreen();
6029         }
6030     }
6031
6032     public void hideBootMessagesLocked() {
6033         if (DEBUG_BOOT) {
6034             RuntimeException here = new RuntimeException("here");
6035             here.fillInStackTrace();
6036             Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
6037                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
6038                     + " mShowingBootMessages=" + mShowingBootMessages
6039                     + " mSystemBooted=" + mSystemBooted, here);
6040         }
6041         if (mShowingBootMessages) {
6042             mShowingBootMessages = false;
6043             mPolicy.hideBootMessages();
6044         }
6045     }
6046
6047     @Override
6048     public void setInTouchMode(boolean mode) {
6049         synchronized(mWindowMap) {
6050             mInTouchMode = mode;
6051         }
6052     }
6053
6054     private void updateCircularDisplayMaskIfNeeded() {
6055         // we're fullscreen and not hosted in an ActivityView
6056         if (mContext.getResources().getConfiguration().isScreenRound()
6057                 && mContext.getResources().getBoolean(
6058                 com.android.internal.R.bool.config_windowShowCircularMask)) {
6059             final int currentUserId;
6060             synchronized(mWindowMap) {
6061                 currentUserId = mCurrentUserId;
6062             }
6063             // Device configuration calls for a circular display mask, but we only enable the mask
6064             // if the accessibility color inversion feature is disabled, as the inverted mask
6065             // causes artifacts.
6066             int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
6067                     Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
6068             int showMask = (inversionState == 1) ? 0 : 1;
6069             Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
6070             m.arg1 = showMask;
6071             mH.sendMessage(m);
6072         }
6073     }
6074
6075     public void showEmulatorDisplayOverlayIfNeeded() {
6076         if (mContext.getResources().getBoolean(
6077                 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
6078                 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
6079                 && Build.IS_EMULATOR) {
6080             mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
6081         }
6082     }
6083
6084     public void showCircularMask(boolean visible) {
6085         synchronized(mWindowMap) {
6086
6087             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6088                     ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
6089             SurfaceControl.openTransaction();
6090             try {
6091                 if (visible) {
6092                     // TODO(multi-display): support multiple displays
6093                     if (mCircularDisplayMask == null) {
6094                         int screenOffset = mContext.getResources().getInteger(
6095                                 com.android.internal.R.integer.config_windowOutsetBottom);
6096                         int maskThickness = mContext.getResources().getDimensionPixelSize(
6097                                 com.android.internal.R.dimen.circular_display_mask_thickness);
6098
6099                         mCircularDisplayMask = new CircularDisplayMask(
6100                                 getDefaultDisplayContentLocked().getDisplay(),
6101                                 mFxSession,
6102                                 mPolicy.windowTypeToLayerLw(
6103                                         WindowManager.LayoutParams.TYPE_POINTER)
6104                                         * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
6105                     }
6106                     mCircularDisplayMask.setVisibility(true);
6107                 } else if (mCircularDisplayMask != null) {
6108                     mCircularDisplayMask.setVisibility(false);
6109                     mCircularDisplayMask = null;
6110                 }
6111             } finally {
6112                 SurfaceControl.closeTransaction();
6113                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6114                         "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
6115             }
6116         }
6117     }
6118
6119     public void showEmulatorDisplayOverlay() {
6120         synchronized(mWindowMap) {
6121
6122             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6123                     ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
6124             SurfaceControl.openTransaction();
6125             try {
6126                 if (mEmulatorDisplayOverlay == null) {
6127                     mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
6128                             mContext,
6129                             getDefaultDisplayContentLocked().getDisplay(),
6130                             mFxSession,
6131                             mPolicy.windowTypeToLayerLw(
6132                                     WindowManager.LayoutParams.TYPE_POINTER)
6133                                     * TYPE_LAYER_MULTIPLIER + 10);
6134                 }
6135                 mEmulatorDisplayOverlay.setVisibility(true);
6136             } finally {
6137                 SurfaceControl.closeTransaction();
6138                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6139                         "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
6140             }
6141         }
6142     }
6143
6144     // TODO: more accounting of which pid(s) turned it on, keep count,
6145     // only allow disables from pids which have count on, etc.
6146     @Override
6147     public void showStrictModeViolation(boolean on) {
6148         int pid = Binder.getCallingPid();
6149         mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
6150     }
6151
6152     private void showStrictModeViolation(int arg, int pid) {
6153         final boolean on = arg != 0;
6154         synchronized(mWindowMap) {
6155             // Ignoring requests to enable the red border from clients
6156             // which aren't on screen.  (e.g. Broadcast Receivers in
6157             // the background..)
6158             if (on) {
6159                 boolean isVisible = false;
6160                 final int numDisplays = mDisplayContents.size();
6161                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6162                     final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6163                     final int numWindows = windows.size();
6164                     for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6165                         final WindowState ws = windows.get(winNdx);
6166                         if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
6167                             isVisible = true;
6168                             break;
6169                         }
6170                     }
6171                 }
6172                 if (!isVisible) {
6173                     return;
6174                 }
6175             }
6176
6177             if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
6178                     ">>> OPEN TRANSACTION showStrictModeViolation");
6179             SurfaceControl.openTransaction();
6180             try {
6181                 // TODO(multi-display): support multiple displays
6182                 if (mStrictModeFlash == null) {
6183                     mStrictModeFlash = new StrictModeFlash(
6184                             getDefaultDisplayContentLocked().getDisplay(), mFxSession);
6185                 }
6186                 mStrictModeFlash.setVisibility(on);
6187             } finally {
6188                 SurfaceControl.closeTransaction();
6189                 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
6190                         "<<< CLOSE TRANSACTION showStrictModeViolation");
6191             }
6192         }
6193     }
6194
6195     @Override
6196     public void setStrictModeVisualIndicatorPreference(String value) {
6197         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
6198     }
6199
6200     private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
6201         if (rot == Surface.ROTATION_90) {
6202             final int tmp = crop.top;
6203             crop.top = dw - crop.right;
6204             crop.right = crop.bottom;
6205             crop.bottom = dw - crop.left;
6206             crop.left = tmp;
6207         } else if (rot == Surface.ROTATION_180) {
6208             int tmp = crop.top;
6209             crop.top = dh - crop.bottom;
6210             crop.bottom = dh - tmp;
6211             tmp = crop.right;
6212             crop.right = dw - crop.left;
6213             crop.left = dw - tmp;
6214         } else if (rot == Surface.ROTATION_270) {
6215             final int tmp = crop.top;
6216             crop.top = crop.left;
6217             crop.left = dh - crop.bottom;
6218             crop.bottom = crop.right;
6219             crop.right = dh - tmp;
6220         }
6221     }
6222
6223     @Override
6224     public Bitmap screenshotWallpaper() {
6225         if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6226                 "screenshotWallpaper()")) {
6227             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6228         }
6229         try {
6230             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
6231             return screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, true, 1f,
6232                     Bitmap.Config.ARGB_8888, true);
6233         } finally {
6234             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
6235         }
6236     }
6237
6238     /**
6239      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
6240      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
6241      * of the target image.
6242      */
6243     @Override
6244     public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
6245         if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6246                 "requestAssistScreenshot()")) {
6247             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6248         }
6249
6250         FgThread.getHandler().post(new Runnable() {
6251             @Override
6252             public void run() {
6253                 Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1,
6254                         true, 1f, Bitmap.Config.ARGB_8888, false);
6255                 try {
6256                     receiver.send(bm);
6257                 } catch (RemoteException e) {
6258                 }
6259             }
6260         });
6261
6262         return true;
6263     }
6264
6265     /**
6266      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
6267      * In portrait mode, it grabs the full screenshot.
6268      *
6269      * @param displayId the Display to take a screenshot of.
6270      * @param width the width of the target bitmap
6271      * @param height the height of the target bitmap
6272      * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
6273      */
6274     @Override
6275     public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
6276             float frameScale) {
6277         if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6278                 "screenshotApplications()")) {
6279             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6280         }
6281         try {
6282             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
6283             return screenshotApplicationsInner(appToken, displayId, width, height, false,
6284                     frameScale, Bitmap.Config.RGB_565, false);
6285         } finally {
6286             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
6287         }
6288     }
6289
6290     /**
6291      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
6292      * In portrait mode, it grabs the full screenshot.
6293      *
6294      * @param displayId the Display to take a screenshot of.
6295      * @param width the width of the target bitmap
6296      * @param height the height of the target bitmap
6297      * @param includeFullDisplay true if the screen should not be cropped before capture
6298      * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
6299      * @param config of the output bitmap
6300      * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
6301      */
6302     Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
6303             boolean includeFullDisplay, float frameScale, Bitmap.Config config,
6304             boolean wallpaperOnly) {
6305         final DisplayContent displayContent;
6306         synchronized(mWindowMap) {
6307             displayContent = getDisplayContentLocked(displayId);
6308             if (displayContent == null) {
6309                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6310                         + ": returning null. No Display for displayId=" + displayId);
6311                 return null;
6312             }
6313         }
6314         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6315         int dw = displayInfo.logicalWidth;
6316         int dh = displayInfo.logicalHeight;
6317         if (dw == 0 || dh == 0) {
6318             if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6319                     + ": returning null. logical widthxheight=" + dw + "x" + dh);
6320             return null;
6321         }
6322
6323         Bitmap bm = null;
6324
6325         int maxLayer = 0;
6326         final Rect frame = new Rect();
6327         final Rect stackBounds = new Rect();
6328
6329         boolean screenshotReady;
6330         int minLayer;
6331         if (appToken == null && !wallpaperOnly) {
6332             screenshotReady = true;
6333             minLayer = 0;
6334         } else {
6335             screenshotReady = false;
6336             minLayer = Integer.MAX_VALUE;
6337         }
6338
6339         WindowState appWin = null;
6340
6341         boolean includeImeInScreenshot;
6342         synchronized(mWindowMap) {
6343             final AppWindowToken imeTargetAppToken =
6344                     mInputMethodTarget != null ? mInputMethodTarget.mAppToken : null;
6345             // We only include the Ime in the screenshot if the app we are screenshoting is the IME
6346             // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
6347             // mode because the frame of the IME might not overlap with that of the app.
6348             // E.g. IME target app at the top in split-screen mode and the IME at the bottom
6349             // overlapping with the bottom app.
6350             includeImeInScreenshot = imeTargetAppToken != null
6351                     && imeTargetAppToken.appToken != null
6352                     && imeTargetAppToken.appToken.asBinder() == appToken
6353                     && !mInputMethodTarget.isInMultiWindowMode();
6354         }
6355
6356         final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
6357                 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
6358
6359         synchronized(mWindowMap) {
6360             // Figure out the part of the screen that is actually the app.
6361             appWin = null;
6362             final WindowList windows = displayContent.getWindowList();
6363             for (int i = windows.size() - 1; i >= 0; i--) {
6364                 WindowState ws = windows.get(i);
6365                 if (!ws.mHasSurface) {
6366                     continue;
6367                 }
6368                 if (ws.mLayer >= aboveAppLayer) {
6369                     continue;
6370                 }
6371                 if (wallpaperOnly && !ws.mIsWallpaper) {
6372                     continue;
6373                 }
6374                 if (ws.mIsImWindow) {
6375                     if (!includeImeInScreenshot) {
6376                         continue;
6377                     }
6378                 } else if (ws.mIsWallpaper) {
6379                     // If this is the wallpaper layer and we're only looking for the wallpaper layer
6380                     // then the target window state is this one.
6381                     if (wallpaperOnly) {
6382                         appWin = ws;
6383                     }
6384
6385                     if (appWin == null) {
6386                         // We have not ran across the target window yet, so it is probably
6387                         // behind the wallpaper. This can happen when the keyguard is up and
6388                         // all windows are moved behind the wallpaper. We don't want to
6389                         // include the wallpaper layer in the screenshot as it will coverup
6390                         // the layer of the target window.
6391                         continue;
6392                     }
6393                     // Fall through. The target window is in front of the wallpaper. For this
6394                     // case we want to include the wallpaper layer in the screenshot because
6395                     // the target window might have some transparent areas.
6396                 } else if (appToken != null) {
6397                     if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
6398                         // This app window is of no interest if it is not associated with the
6399                         // screenshot app.
6400                         continue;
6401                     }
6402                     appWin = ws;
6403                 }
6404
6405                 // Include this window.
6406
6407                 final WindowStateAnimator winAnim = ws.mWinAnimator;
6408                 int layer = winAnim.mSurfaceController.getLayer();
6409                 if (maxLayer < layer) {
6410                     maxLayer = layer;
6411                 }
6412                 if (minLayer > layer) {
6413                     minLayer = layer;
6414                 }
6415
6416                 // Don't include wallpaper in bounds calculation
6417                 if (!includeFullDisplay && !ws.mIsWallpaper) {
6418                     final Rect wf = ws.mFrame;
6419                     final Rect cr = ws.mContentInsets;
6420                     int left = wf.left + cr.left;
6421                     int top = wf.top + cr.top;
6422                     int right = wf.right - cr.right;
6423                     int bottom = wf.bottom - cr.bottom;
6424                     frame.union(left, top, right, bottom);
6425                     ws.getVisibleBounds(stackBounds);
6426                     if (!Rect.intersects(frame, stackBounds)) {
6427                         // Set frame empty if there's no intersection.
6428                         frame.setEmpty();
6429                     }
6430                 }
6431
6432                 final boolean foundTargetWs =
6433                         (ws.mAppToken != null && ws.mAppToken.token == appToken)
6434                         || (appWin != null && wallpaperOnly);
6435                 if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
6436                     screenshotReady = true;
6437                 }
6438
6439                 if (ws.isObscuringFullscreen(displayInfo)){
6440                     break;
6441                 }
6442             }
6443
6444             if (appToken != null && appWin == null) {
6445                 // Can't find a window to snapshot.
6446                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
6447                         "Screenshot: Couldn't find a surface matching " + appToken);
6448                 return null;
6449             }
6450
6451             if (!screenshotReady) {
6452                 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
6453                         " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
6454                         appWin.mWinAnimator.mDrawState)));
6455                 return null;
6456             }
6457
6458             // Screenshot is ready to be taken. Everything from here below will continue
6459             // through the bottom of the loop and return a value. We only stay in the loop
6460             // because we don't want to release the mWindowMap lock until the screenshot is
6461             // taken.
6462
6463             if (maxLayer == 0) {
6464                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6465                         + ": returning null maxLayer=" + maxLayer);
6466                 return null;
6467             }
6468
6469             if (!includeFullDisplay) {
6470                 // Constrain frame to the screen size.
6471                 if (!frame.intersect(0, 0, dw, dh)) {
6472                     frame.setEmpty();
6473                 }
6474             } else {
6475                 // Caller just wants entire display.
6476                 frame.set(0, 0, dw, dh);
6477             }
6478             if (frame.isEmpty()) {
6479                 return null;
6480             }
6481
6482             if (width < 0) {
6483                 width = (int) (frame.width() * frameScale);
6484             }
6485             if (height < 0) {
6486                 height = (int) (frame.height() * frameScale);
6487             }
6488
6489             // Tell surface flinger what part of the image to crop. Take the top
6490             // right part of the application, and crop the larger dimension to fit.
6491             Rect crop = new Rect(frame);
6492             if (width / (float) frame.width() < height / (float) frame.height()) {
6493                 int cropWidth = (int)((float)width / (float)height * frame.height());
6494                 crop.right = crop.left + cropWidth;
6495             } else {
6496                 int cropHeight = (int)((float)height / (float)width * frame.width());
6497                 crop.bottom = crop.top + cropHeight;
6498             }
6499
6500             // The screenshot API does not apply the current screen rotation.
6501             int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6502
6503             if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6504                 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6505             }
6506
6507             // Surfaceflinger is not aware of orientation, so convert our logical
6508             // crop to surfaceflinger's portrait orientation.
6509             convertCropForSurfaceFlinger(crop, rot, dw, dh);
6510
6511             if (DEBUG_SCREENSHOT) {
6512                 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6513                         + maxLayer + " appToken=" + appToken);
6514                 for (int i = 0; i < windows.size(); i++) {
6515                     WindowState win = windows.get(i);
6516                     WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
6517                     Slog.i(TAG_WM, win + ": " + win.mLayer
6518                             + " animLayer=" + win.mWinAnimator.mAnimLayer
6519                             + " surfaceLayer=" + ((controller == null)
6520                                 ? "null" : controller.getLayer()));
6521                 }
6522             }
6523
6524             ScreenRotationAnimation screenRotationAnimation =
6525                     mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6526             final boolean inRotation = screenRotationAnimation != null &&
6527                     screenRotationAnimation.isAnimating();
6528             if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
6529                     "Taking screenshot while rotating");
6530
6531             // We force pending transactions to flush before taking
6532             // the screenshot by pushing an empty synchronous transaction.
6533             SurfaceControl.openTransaction();
6534             SurfaceControl.closeTransactionSync();
6535
6536             bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6537                     inRotation, rot);
6538             if (bm == null) {
6539                 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6540                         + ") to layer " + maxLayer);
6541                 return null;
6542             }
6543         }
6544
6545         if (DEBUG_SCREENSHOT) {
6546             // TEST IF IT's ALL BLACK
6547             int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6548             bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6549             boolean allBlack = true;
6550             final int firstColor = buffer[0];
6551             for (int i = 0; i < buffer.length; i++) {
6552                 if (buffer[i] != firstColor) {
6553                     allBlack = false;
6554                     break;
6555                 }
6556             }
6557             if (allBlack) {
6558                 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
6559                         Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6560                         (appWin != null ?
6561                                 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
6562                         " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6563             }
6564         }
6565
6566         // Create a copy of the screenshot that is immutable and backed in ashmem.
6567         // This greatly reduces the overhead of passing the bitmap between processes.
6568         Bitmap ret = bm.createAshmemBitmap(config);
6569         bm.recycle();
6570         return ret;
6571     }
6572
6573     /**
6574      * Freeze rotation changes.  (Enable "rotation lock".)
6575      * Persists across reboots.
6576      * @param rotation The desired rotation to freeze to, or -1 to use the
6577      * current rotation.
6578      */
6579     @Override
6580     public void freezeRotation(int rotation) {
6581         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6582                 "freezeRotation()")) {
6583             throw new SecurityException("Requires SET_ORIENTATION permission");
6584         }
6585         if (rotation < -1 || rotation > Surface.ROTATION_270) {
6586             throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6587                     + "rotation constant.");
6588         }
6589
6590         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation);
6591
6592         long origId = Binder.clearCallingIdentity();
6593         try {
6594             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6595                     rotation == -1 ? mRotation : rotation);
6596         } finally {
6597             Binder.restoreCallingIdentity(origId);
6598         }
6599
6600         updateRotationUnchecked(false, false);
6601     }
6602
6603     /**
6604      * Thaw rotation changes.  (Disable "rotation lock".)
6605      * Persists across reboots.
6606      */
6607     @Override
6608     public void thawRotation() {
6609         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6610                 "thawRotation()")) {
6611             throw new SecurityException("Requires SET_ORIENTATION permission");
6612         }
6613
6614         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation);
6615
6616         long origId = Binder.clearCallingIdentity();
6617         try {
6618             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6619                     777); // rot not used
6620         } finally {
6621             Binder.restoreCallingIdentity(origId);
6622         }
6623
6624         updateRotationUnchecked(false, false);
6625     }
6626
6627     /**
6628      * Recalculate the current rotation.
6629      *
6630      * Called by the window manager policy whenever the state of the system changes
6631      * such that the current rotation might need to be updated, such as when the
6632      * device is docked or rotated into a new posture.
6633      */
6634     @Override
6635     public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6636         updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6637     }
6638
6639     /**
6640      * Temporarily pauses rotation changes until resumed.
6641      *
6642      * This can be used to prevent rotation changes from occurring while the user is
6643      * performing certain operations, such as drag and drop.
6644      *
6645      * This call nests and must be matched by an equal number of calls to
6646      * {@link #resumeRotationLocked}.
6647      */
6648     void pauseRotationLocked() {
6649         mDeferredRotationPauseCount += 1;
6650     }
6651
6652     /**
6653      * Resumes normal rotation changes after being paused.
6654      */
6655     void resumeRotationLocked() {
6656         if (mDeferredRotationPauseCount > 0) {
6657             mDeferredRotationPauseCount -= 1;
6658             if (mDeferredRotationPauseCount == 0) {
6659                 boolean changed = updateRotationUncheckedLocked(false);
6660                 if (changed) {
6661                     mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6662                 }
6663             }
6664         }
6665     }
6666
6667     public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6668         if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked("
6669                    + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6670
6671         long origId = Binder.clearCallingIdentity();
6672         boolean changed;
6673         synchronized(mWindowMap) {
6674             changed = updateRotationUncheckedLocked(false);
6675             if (!changed || forceRelayout) {
6676                 getDefaultDisplayContentLocked().layoutNeeded = true;
6677                 mWindowPlacerLocked.performSurfacePlacement();
6678             }
6679         }
6680
6681         if (changed || alwaysSendConfiguration) {
6682             sendNewConfiguration();
6683         }
6684
6685         Binder.restoreCallingIdentity(origId);
6686     }
6687
6688
6689     // TODO(multidisplay): Rotate any display?
6690     /**
6691      * Updates the current rotation.
6692      *
6693      * Returns true if the rotation has been changed.  In this case YOU
6694      * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6695      */
6696     public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6697         if (mDeferredRotationPauseCount > 0) {
6698             // Rotation updates have been paused temporarily.  Defer the update until
6699             // updates have been resumed.
6700             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
6701             return false;
6702         }
6703
6704         ScreenRotationAnimation screenRotationAnimation =
6705                 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6706         if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6707             // Rotation updates cannot be performed while the previous rotation change
6708             // animation is still in progress.  Skip this update.  We will try updating
6709             // again after the animation is finished and the display is unfrozen.
6710             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
6711             return false;
6712         }
6713
6714         if (!mDisplayEnabled) {
6715             // No point choosing a rotation if the display is not enabled.
6716             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
6717             return false;
6718         }
6719
6720         // TODO: Implement forced rotation changes.
6721         //       Set mAltOrientation to indicate that the application is receiving
6722         //       an orientation that has different metrics than it expected.
6723         //       eg. Portrait instead of Landscape.
6724
6725         int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
6726         boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6727                 mLastOrientation, rotation);
6728
6729         if (DEBUG_ORIENTATION) {
6730             Slog.v(TAG_WM, "Selected orientation "
6731                     + mLastOrientation + ", got rotation " + rotation
6732                     + " which has " + (altOrientation ? "incompatible" : "compatible")
6733                     + " metrics");
6734         }
6735
6736         if (mRotation == rotation && mAltOrientation == altOrientation) {
6737             // No change.
6738             return false;
6739         }
6740
6741         if (DEBUG_ORIENTATION) {
6742             Slog.v(TAG_WM,
6743                 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6744                 + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6745                 + ", lastOrientation=" + mLastOrientation);
6746         }
6747
6748         int oldRotation = mRotation;
6749
6750         mRotation = rotation;
6751         mAltOrientation = altOrientation;
6752         mPolicy.setRotationLw(mRotation);
6753
6754         mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
6755         mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6756         mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6757         mWaitingForConfig = true;
6758         final DisplayContent displayContent = getDefaultDisplayContentLocked();
6759         displayContent.layoutNeeded = true;
6760         final int[] anim = new int[2];
6761         if (displayContent.isDimming()) {
6762             anim[0] = anim[1] = 0;
6763         } else {
6764             mPolicy.selectRotationAnimationLw(anim);
6765         }
6766         boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, mRotation);
6767         final WindowList windows = displayContent.getWindowList();
6768         // We can't rotate seamlessly while an existing seamless rotation is still
6769         // waiting on windows to finish drawing.
6770         if (rotateSeamlessly) {
6771             for (int i = windows.size() - 1; i >= 0; i--) {
6772                 WindowState w = windows.get(i);
6773                 if (w.mSeamlesslyRotated) {
6774                     rotateSeamlessly = false;
6775                     break;
6776                 }
6777                 // In what can only be called an unfortunate workaround we require
6778                 // seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE
6779                 // flag. Due to limitations in the client API, there is no way for
6780                 // the client to set this flag in a race free fashion. If we seamlessly rotate
6781                 // a window which does not have this flag, but then gains it, we will get
6782                 // an incorrect visual result (rotated viewfinder). This means if we want to
6783                 // support seamlessly rotating windows which could gain this flag, we can't
6784                 // rotate windows without it. This limits seamless rotation in N to camera framework
6785                 // users, windows without children, and native code. This is unfortunate but
6786                 // having the camera work is our primary goal.
6787                 if (w.isChildWindow() & w.isVisibleNow() &&
6788                         !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) {
6789                     rotateSeamlessly = false;
6790                 }
6791             }
6792         }
6793
6794         if (!rotateSeamlessly) {
6795             startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6796             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6797             screenRotationAnimation =
6798                 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6799         } else {
6800             // The screen rotation animation uses a screenshot to freeze the screen
6801             // while windows resize underneath.
6802             // When we are rotating seamlessly, we allow the elements to transition
6803             // to their rotated state independently and without a freeze required.
6804             screenRotationAnimation = null;
6805         }
6806
6807         // We need to update our screen size information to match the new rotation. If the rotation
6808         // has actually changed then this method will return true and, according to the comment at
6809         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
6810         // By updating the Display info here it will be available to
6811         // computeScreenConfigurationLocked later.
6812         updateDisplayAndOrientationLocked(mCurConfiguration.uiMode);
6813
6814         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6815         if (!inTransaction) {
6816             if (SHOW_TRANSACTIONS) {
6817                 Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
6818             }
6819             SurfaceControl.openTransaction();
6820         }
6821         try {
6822             // NOTE: We disable the rotation in the emulator because
6823             //       it doesn't support hardware OpenGL emulation yet.
6824             if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6825                     && screenRotationAnimation.hasScreenshot()) {
6826                 if (screenRotationAnimation.setRotationInTransaction(
6827                         rotation, mFxSession,
6828                         MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6829                         displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6830                     scheduleAnimationLocked();
6831                 }
6832             }
6833
6834             if (rotateSeamlessly) {
6835                 for (int i = windows.size() - 1; i >= 0; i--) {
6836                     WindowState w = windows.get(i);
6837                     w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation);
6838                 }
6839             }
6840
6841             mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6842         } finally {
6843             if (!inTransaction) {
6844                 SurfaceControl.closeTransaction();
6845                 if (SHOW_LIGHT_TRANSACTIONS) {
6846                     Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
6847                 }
6848             }
6849         }
6850
6851         for (int i = windows.size() - 1; i >= 0; i--) {
6852             WindowState w = windows.get(i);
6853             // Discard surface after orientation change, these can't be reused.
6854             if (w.mAppToken != null) {
6855                 w.mAppToken.destroySavedSurfaces();
6856             }
6857             if (w.mHasSurface && !rotateSeamlessly) {
6858                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
6859                 w.mOrientationChanging = true;
6860                 mWindowPlacerLocked.mOrientationChangeComplete = false;
6861                 w.mLastFreezeDuration = 0;
6862             }
6863         }
6864         if (rotateSeamlessly) {
6865             mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT);
6866             mH.sendEmptyMessageDelayed(H.SEAMLESS_ROTATION_TIMEOUT, SEAMLESS_ROTATION_TIMEOUT_DURATION);
6867         }
6868
6869         for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6870             try {
6871                 mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6872             } catch (RemoteException e) {
6873             }
6874         }
6875
6876         // TODO (multidisplay): Magnification is supported only for the default display.
6877         // Announce rotation only if we will not animate as we already have the
6878         // windows in final state. Otherwise, we make this call at the rotation end.
6879         if (screenRotationAnimation == null && mAccessibilityController != null
6880                 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6881             mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),
6882                     rotation);
6883         }
6884
6885         return true;
6886     }
6887
6888     @Override
6889     public int getRotation() {
6890         return mRotation;
6891     }
6892
6893     @Override
6894     public boolean isRotationFrozen() {
6895         return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6896     }
6897
6898     @Override
6899     public int watchRotation(IRotationWatcher watcher) {
6900         final IBinder watcherBinder = watcher.asBinder();
6901         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6902             @Override
6903             public void binderDied() {
6904                 synchronized (mWindowMap) {
6905                     for (int i=0; i<mRotationWatchers.size(); i++) {
6906                         if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6907                             RotationWatcher removed = mRotationWatchers.remove(i);
6908                             IBinder binder = removed.watcher.asBinder();
6909                             if (binder != null) {
6910                                 binder.unlinkToDeath(this, 0);
6911                             }
6912                             i--;
6913                         }
6914                     }
6915                 }
6916             }
6917         };
6918
6919         synchronized (mWindowMap) {
6920             try {
6921                 watcher.asBinder().linkToDeath(dr, 0);
6922                 mRotationWatchers.add(new RotationWatcher(watcher, dr));
6923             } catch (RemoteException e) {
6924                 // Client died, no cleanup needed.
6925             }
6926
6927             return mRotation;
6928         }
6929     }
6930
6931     @Override
6932     public void removeRotationWatcher(IRotationWatcher watcher) {
6933         final IBinder watcherBinder = watcher.asBinder();
6934         synchronized (mWindowMap) {
6935             for (int i=0; i<mRotationWatchers.size(); i++) {
6936                 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6937                 if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6938                     RotationWatcher removed = mRotationWatchers.remove(i);
6939                     IBinder binder = removed.watcher.asBinder();
6940                     if (binder != null) {
6941                         binder.unlinkToDeath(removed.deathRecipient, 0);
6942                     }
6943                     i--;
6944                 }
6945             }
6946         }
6947     }
6948
6949     /**
6950      * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6951      * theme attribute) on devices that feature a physical options menu key attempt to position
6952      * their menu panel window along the edge of the screen nearest the physical menu key.
6953      * This lowers the travel distance between invoking the menu panel and selecting
6954      * a menu option.
6955      *
6956      * This method helps control where that menu is placed. Its current implementation makes
6957      * assumptions about the menu key and its relationship to the screen based on whether
6958      * the device's natural orientation is portrait (width < height) or landscape.
6959      *
6960      * The menu key is assumed to be located along the bottom edge of natural-portrait
6961      * devices and along the right edge of natural-landscape devices. If these assumptions
6962      * do not hold for the target device, this method should be changed to reflect that.
6963      *
6964      * @return A {@link Gravity} value for placing the options menu window
6965      */
6966     @Override
6967     public int getPreferredOptionsPanelGravity() {
6968         synchronized (mWindowMap) {
6969             final int rotation = getRotation();
6970
6971             // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6972             final DisplayContent displayContent = getDefaultDisplayContentLocked();
6973             if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6974                 // On devices with a natural orientation of portrait
6975                 switch (rotation) {
6976                     default:
6977                     case Surface.ROTATION_0:
6978                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6979                     case Surface.ROTATION_90:
6980                         return Gravity.RIGHT | Gravity.BOTTOM;
6981                     case Surface.ROTATION_180:
6982                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6983                     case Surface.ROTATION_270:
6984                         return Gravity.START | Gravity.BOTTOM;
6985                 }
6986             }
6987
6988             // On devices with a natural orientation of landscape
6989             switch (rotation) {
6990                 default:
6991                 case Surface.ROTATION_0:
6992                     return Gravity.RIGHT | Gravity.BOTTOM;
6993                 case Surface.ROTATION_90:
6994                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6995                 case Surface.ROTATION_180:
6996                     return Gravity.START | Gravity.BOTTOM;
6997                 case Surface.ROTATION_270:
6998                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6999             }
7000         }
7001     }
7002
7003     /**
7004      * Starts the view server on the specified port.
7005      *
7006      * @param port The port to listener to.
7007      *
7008      * @return True if the server was successfully started, false otherwise.
7009      *
7010      * @see com.android.server.wm.ViewServer
7011      * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
7012      */
7013     @Override
7014     public boolean startViewServer(int port) {
7015         if (isSystemSecure()) {
7016             return false;
7017         }
7018
7019         if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
7020             return false;
7021         }
7022
7023         if (port < 1024) {
7024             return false;
7025         }
7026
7027         if (mViewServer != null) {
7028             if (!mViewServer.isRunning()) {
7029                 try {
7030                     return mViewServer.start();
7031                 } catch (IOException e) {
7032                     Slog.w(TAG_WM, "View server did not start");
7033                 }
7034             }
7035             return false;
7036         }
7037
7038         try {
7039             mViewServer = new ViewServer(this, port);
7040             return mViewServer.start();
7041         } catch (IOException e) {
7042             Slog.w(TAG_WM, "View server did not start");
7043         }
7044         return false;
7045     }
7046
7047     private boolean isSystemSecure() {
7048         return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
7049                 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
7050     }
7051
7052     /**
7053      * Stops the view server if it exists.
7054      *
7055      * @return True if the server stopped, false if it wasn't started or
7056      *         couldn't be stopped.
7057      *
7058      * @see com.android.server.wm.ViewServer
7059      */
7060     @Override
7061     public boolean stopViewServer() {
7062         if (isSystemSecure()) {
7063             return false;
7064         }
7065
7066         if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
7067             return false;
7068         }
7069
7070         if (mViewServer != null) {
7071             return mViewServer.stop();
7072         }
7073         return false;
7074     }
7075
7076     /**
7077      * Indicates whether the view server is running.
7078      *
7079      * @return True if the server is running, false otherwise.
7080      *
7081      * @see com.android.server.wm.ViewServer
7082      */
7083     @Override
7084     public boolean isViewServerRunning() {
7085         if (isSystemSecure()) {
7086             return false;
7087         }
7088
7089         if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
7090             return false;
7091         }
7092
7093         return mViewServer != null && mViewServer.isRunning();
7094     }
7095
7096     /**
7097      * Lists all availble windows in the system. The listing is written in the
7098      * specified Socket's output stream with the following syntax:
7099      * windowHashCodeInHexadecimal windowName
7100      * Each line of the ouput represents a different window.
7101      *
7102      * @param client The remote client to send the listing to.
7103      * @return False if an error occured, true otherwise.
7104      */
7105     boolean viewServerListWindows(Socket client) {
7106         if (isSystemSecure()) {
7107             return false;
7108         }
7109
7110         boolean result = true;
7111
7112         WindowList windows = new WindowList();
7113         synchronized (mWindowMap) {
7114             //noinspection unchecked
7115             final int numDisplays = mDisplayContents.size();
7116             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7117                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
7118                 windows.addAll(displayContent.getWindowList());
7119             }
7120         }
7121
7122         BufferedWriter out = null;
7123
7124         // Any uncaught exception will crash the system process
7125         try {
7126             OutputStream clientStream = client.getOutputStream();
7127             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
7128
7129             final int count = windows.size();
7130             for (int i = 0; i < count; i++) {
7131                 final WindowState w = windows.get(i);
7132                 out.write(Integer.toHexString(System.identityHashCode(w)));
7133                 out.write(' ');
7134                 out.append(w.mAttrs.getTitle());
7135                 out.write('\n');
7136             }
7137
7138             out.write("DONE.\n");
7139             out.flush();
7140         } catch (Exception e) {
7141             result = false;
7142         } finally {
7143             if (out != null) {
7144                 try {
7145                     out.close();
7146                 } catch (IOException e) {
7147                     result = false;
7148                 }
7149             }
7150         }
7151
7152         return result;
7153     }
7154
7155     // TODO(multidisplay): Extend to multiple displays.
7156     /**
7157      * Returns the focused window in the following format:
7158      * windowHashCodeInHexadecimal windowName
7159      *
7160      * @param client The remote client to send the listing to.
7161      * @return False if an error occurred, true otherwise.
7162      */
7163     boolean viewServerGetFocusedWindow(Socket client) {
7164         if (isSystemSecure()) {
7165             return false;
7166         }
7167
7168         boolean result = true;
7169
7170         WindowState focusedWindow = getFocusedWindow();
7171
7172         BufferedWriter out = null;
7173
7174         // Any uncaught exception will crash the system process
7175         try {
7176             OutputStream clientStream = client.getOutputStream();
7177             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
7178
7179             if(focusedWindow != null) {
7180                 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
7181                 out.write(' ');
7182                 out.append(focusedWindow.mAttrs.getTitle());
7183             }
7184             out.write('\n');
7185             out.flush();
7186         } catch (Exception e) {
7187             result = false;
7188         } finally {
7189             if (out != null) {
7190                 try {
7191                     out.close();
7192                 } catch (IOException e) {
7193                     result = false;
7194                 }
7195             }
7196         }
7197
7198         return result;
7199     }
7200
7201     /**
7202      * Sends a command to a target window. The result of the command, if any, will be
7203      * written in the output stream of the specified socket.
7204      *
7205      * The parameters must follow this syntax:
7206      * windowHashcode extra
7207      *
7208      * Where XX is the length in characeters of the windowTitle.
7209      *
7210      * The first parameter is the target window. The window with the specified hashcode
7211      * will be the target. If no target can be found, nothing happens. The extra parameters
7212      * will be delivered to the target window and as parameters to the command itself.
7213      *
7214      * @param client The remote client to sent the result, if any, to.
7215      * @param command The command to execute.
7216      * @param parameters The command parameters.
7217      *
7218      * @return True if the command was successfully delivered, false otherwise. This does
7219      *         not indicate whether the command itself was successful.
7220      */
7221     boolean viewServerWindowCommand(Socket client, String command, String parameters) {
7222         if (isSystemSecure()) {
7223             return false;
7224         }
7225
7226         boolean success = true;
7227         Parcel data = null;
7228         Parcel reply = null;
7229
7230         BufferedWriter out = null;
7231
7232         // Any uncaught exception will crash the system process
7233         try {
7234             // Find the hashcode of the window
7235             int index = parameters.indexOf(' ');
7236             if (index == -1) {
7237                 index = parameters.length();
7238             }
7239             final String code = parameters.substring(0, index);
7240             int hashCode = (int) Long.parseLong(code, 16);
7241
7242             // Extract the command's parameter after the window description
7243             if (index < parameters.length()) {
7244                 parameters = parameters.substring(index + 1);
7245             } else {
7246                 parameters = "";
7247             }
7248
7249             final WindowState window = findWindow(hashCode);
7250             if (window == null) {
7251                 return false;
7252             }
7253
7254             data = Parcel.obtain();
7255             data.writeInterfaceToken("android.view.IWindow");
7256             data.writeString(command);
7257             data.writeString(parameters);
7258             data.writeInt(1);
7259             ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
7260
7261             reply = Parcel.obtain();
7262
7263             final IBinder binder = window.mClient.asBinder();
7264             // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
7265             binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
7266
7267             reply.readException();
7268
7269             if (!client.isOutputShutdown()) {
7270                 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
7271                 out.write("DONE\n");
7272                 out.flush();
7273             }
7274
7275         } catch (Exception e) {
7276             Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
7277             success = false;
7278         } finally {
7279             if (data != null) {
7280                 data.recycle();
7281             }
7282             if (reply != null) {
7283                 reply.recycle();
7284             }
7285             if (out != null) {
7286                 try {
7287                     out.close();
7288                 } catch (IOException e) {
7289
7290                 }
7291             }
7292         }
7293
7294         return success;
7295     }
7296
7297     public void addWindowChangeListener(WindowChangeListener listener) {
7298         synchronized(mWindowMap) {
7299             mWindowChangeListeners.add(listener);
7300         }
7301     }
7302
7303     public void removeWindowChangeListener(WindowChangeListener listener) {
7304         synchronized(mWindowMap) {
7305             mWindowChangeListeners.remove(listener);
7306         }
7307     }
7308
7309     private void notifyWindowsChanged() {
7310         WindowChangeListener[] windowChangeListeners;
7311         synchronized(mWindowMap) {
7312             if(mWindowChangeListeners.isEmpty()) {
7313                 return;
7314             }
7315             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
7316             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
7317         }
7318         int N = windowChangeListeners.length;
7319         for(int i = 0; i < N; i++) {
7320             windowChangeListeners[i].windowsChanged();
7321         }
7322     }
7323
7324     private void notifyFocusChanged() {
7325         WindowChangeListener[] windowChangeListeners;
7326         synchronized(mWindowMap) {
7327             if(mWindowChangeListeners.isEmpty()) {
7328                 return;
7329             }
7330             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
7331             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
7332         }
7333         int N = windowChangeListeners.length;
7334         for(int i = 0; i < N; i++) {
7335             windowChangeListeners[i].focusChanged();
7336         }
7337     }
7338
7339     private WindowState findWindow(int hashCode) {
7340         if (hashCode == -1) {
7341             // TODO(multidisplay): Extend to multiple displays.
7342             return getFocusedWindow();
7343         }
7344
7345         synchronized (mWindowMap) {
7346             final int numDisplays = mDisplayContents.size();
7347             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7348                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7349                 final int numWindows = windows.size();
7350                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7351                     final WindowState w = windows.get(winNdx);
7352                     if (System.identityHashCode(w) == hashCode) {
7353                         return w;
7354                     }
7355                 }
7356             }
7357         }
7358
7359         return null;
7360     }
7361
7362     /*
7363      * Instruct the Activity Manager to fetch the current configuration and broadcast
7364      * that to config-changed listeners if appropriate.
7365      */
7366     void sendNewConfiguration() {
7367         try {
7368             mActivityManager.updateConfiguration(null);
7369         } catch (RemoteException e) {
7370         }
7371     }
7372
7373     public Configuration computeNewConfiguration() {
7374         synchronized (mWindowMap) {
7375             return computeNewConfigurationLocked();
7376         }
7377     }
7378
7379     private Configuration computeNewConfigurationLocked() {
7380         if (!mDisplayReady) {
7381             return null;
7382         }
7383         Configuration config = new Configuration();
7384         config.fontScale = 0;
7385         computeScreenConfigurationLocked(config);
7386         return config;
7387     }
7388
7389     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode,
7390             int dw, int dh) {
7391         // TODO: Multidisplay: for now only use with default display.
7392         final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode);
7393         if (width < displayInfo.smallestNominalAppWidth) {
7394             displayInfo.smallestNominalAppWidth = width;
7395         }
7396         if (width > displayInfo.largestNominalAppWidth) {
7397             displayInfo.largestNominalAppWidth = width;
7398         }
7399         final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode);
7400         if (height < displayInfo.smallestNominalAppHeight) {
7401             displayInfo.smallestNominalAppHeight = height;
7402         }
7403         if (height > displayInfo.largestNominalAppHeight) {
7404             displayInfo.largestNominalAppHeight = height;
7405         }
7406     }
7407
7408     private int reduceConfigLayout(int curLayout, int rotation, float density,
7409             int dw, int dh, int uiMode) {
7410         // TODO: Multidisplay: for now only use with default display.
7411         // Get the app screen size at this rotation.
7412         int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7413         int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7414
7415         // Compute the screen layout size class for this rotation.
7416         int longSize = w;
7417         int shortSize = h;
7418         if (longSize < shortSize) {
7419             int tmp = longSize;
7420             longSize = shortSize;
7421             shortSize = tmp;
7422         }
7423         longSize = (int)(longSize/density);
7424         shortSize = (int)(shortSize/density);
7425         return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
7426     }
7427
7428     private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
7429                   int uiMode, int dw, int dh, float density, Configuration outConfig) {
7430         // TODO: Multidisplay: for now only use with default display.
7431
7432         // We need to determine the smallest width that will occur under normal
7433         // operation.  To this, start with the base screen size and compute the
7434         // width under the different possible rotations.  We need to un-rotate
7435         // the current screen dimensions before doing this.
7436         int unrotDw, unrotDh;
7437         if (rotated) {
7438             unrotDw = dh;
7439             unrotDh = dw;
7440         } else {
7441             unrotDw = dw;
7442             unrotDh = dh;
7443         }
7444         displayInfo.smallestNominalAppWidth = 1<<30;
7445         displayInfo.smallestNominalAppHeight = 1<<30;
7446         displayInfo.largestNominalAppWidth = 0;
7447         displayInfo.largestNominalAppHeight = 0;
7448         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
7449         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
7450         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
7451         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
7452         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
7453         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
7454         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
7455         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
7456         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
7457         outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
7458         outConfig.screenLayout = sl;
7459     }
7460
7461     private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
7462             DisplayMetrics dm, int dw, int dh) {
7463         // TODO: Multidisplay: for now only use with default display.
7464         dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7465         dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7466         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
7467         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
7468         if (curSize == 0 || size < curSize) {
7469             curSize = size;
7470         }
7471         return curSize;
7472     }
7473
7474     private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh) {
7475         // TODO: Multidisplay: for now only use with default display.
7476         mTmpDisplayMetrics.setTo(dm);
7477         final DisplayMetrics tmpDm = mTmpDisplayMetrics;
7478         final int unrotDw, unrotDh;
7479         if (rotated) {
7480             unrotDw = dh;
7481             unrotDh = dw;
7482         } else {
7483             unrotDw = dw;
7484             unrotDh = dh;
7485         }
7486         int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh);
7487         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw);
7488         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh);
7489         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw);
7490         return sw;
7491     }
7492
7493     /** Do not call if mDisplayReady == false */
7494     DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
7495         // TODO(multidisplay): For now, apply Configuration to main screen only.
7496         final DisplayContent displayContent = getDefaultDisplayContentLocked();
7497
7498         // Use the effective "visual" dimensions based on current rotation
7499         final boolean rotated = (mRotation == Surface.ROTATION_90
7500                 || mRotation == Surface.ROTATION_270);
7501         final int realdw = rotated ?
7502                 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
7503         final int realdh = rotated ?
7504                 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
7505         int dw = realdw;
7506         int dh = realdh;
7507
7508         if (mAltOrientation) {
7509             if (realdw > realdh) {
7510                 // Turn landscape into portrait.
7511                 int maxw = (int)(realdh/1.3f);
7512                 if (maxw < realdw) {
7513                     dw = maxw;
7514                 }
7515             } else {
7516                 // Turn portrait into landscape.
7517                 int maxh = (int)(realdw/1.3f);
7518                 if (maxh < realdh) {
7519                     dh = maxh;
7520                 }
7521             }
7522         }
7523
7524         // Update application display metrics.
7525         final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode);
7526         final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode);
7527         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7528         displayInfo.rotation = mRotation;
7529         displayInfo.logicalWidth = dw;
7530         displayInfo.logicalHeight = dh;
7531         displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7532         displayInfo.appWidth = appWidth;
7533         displayInfo.appHeight = appHeight;
7534         displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7535                 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7536         displayInfo.getAppMetrics(mDisplayMetrics);
7537         if (displayContent.mDisplayScalingDisabled) {
7538             displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
7539         } else {
7540             displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
7541         }
7542
7543         mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7544                 displayContent.getDisplayId(), displayInfo);
7545
7546         displayContent.mBaseDisplayRect.set(0, 0, dw, dh);
7547         if (false) {
7548             Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);
7549         }
7550
7551         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
7552                 mCompatDisplayMetrics);
7553         return displayInfo;
7554     }
7555
7556     /** Do not call if mDisplayReady == false */
7557     void computeScreenConfigurationLocked(Configuration config) {
7558         final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(
7559                 config.uiMode);
7560
7561         final int dw = displayInfo.logicalWidth;
7562         final int dh = displayInfo.logicalHeight;
7563         config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
7564                 Configuration.ORIENTATION_LANDSCAPE;
7565         config.screenWidthDp =
7566                 (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) /
7567                         mDisplayMetrics.density);
7568         config.screenHeightDp =
7569                 (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) /
7570                         mDisplayMetrics.density);
7571         final boolean rotated = (mRotation == Surface.ROTATION_90
7572                 || mRotation == Surface.ROTATION_270);
7573
7574         computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh,
7575                 mDisplayMetrics.density, config);
7576
7577         config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
7578                 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
7579                         ? Configuration.SCREENLAYOUT_ROUND_YES
7580                         : Configuration.SCREENLAYOUT_ROUND_NO);
7581
7582         config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7583         config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7584         config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode,
7585                 mDisplayMetrics, dw, dh);
7586         config.densityDpi = displayInfo.logicalDensityDpi;
7587
7588         // Update the configuration based on available input devices, lid switch,
7589         // and platform configuration.
7590         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7591         config.keyboard = Configuration.KEYBOARD_NOKEYS;
7592         config.navigation = Configuration.NAVIGATION_NONAV;
7593
7594         int keyboardPresence = 0;
7595         int navigationPresence = 0;
7596         final InputDevice[] devices = mInputManager.getInputDevices();
7597         final int len = devices.length;
7598         for (int i = 0; i < len; i++) {
7599             InputDevice device = devices[i];
7600             if (!device.isVirtual()) {
7601                 final int sources = device.getSources();
7602                 final int presenceFlag = device.isExternal() ?
7603                         WindowManagerPolicy.PRESENCE_EXTERNAL :
7604                                 WindowManagerPolicy.PRESENCE_INTERNAL;
7605
7606                 if (mIsTouchDevice) {
7607                     if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7608                             InputDevice.SOURCE_TOUCHSCREEN) {
7609                         config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7610                     }
7611                 } else {
7612                     config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7613                 }
7614
7615                 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7616                     config.navigation = Configuration.NAVIGATION_TRACKBALL;
7617                     navigationPresence |= presenceFlag;
7618                 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7619                         && config.navigation == Configuration.NAVIGATION_NONAV) {
7620                     config.navigation = Configuration.NAVIGATION_DPAD;
7621                     navigationPresence |= presenceFlag;
7622                 }
7623
7624                 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7625                     config.keyboard = Configuration.KEYBOARD_QWERTY;
7626                     keyboardPresence |= presenceFlag;
7627                 }
7628             }
7629         }
7630
7631         if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
7632             config.navigation = Configuration.NAVIGATION_DPAD;
7633             navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
7634         }
7635
7636         // Determine whether a hard keyboard is available and enabled.
7637         boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7638         if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7639             mHardKeyboardAvailable = hardKeyboardAvailable;
7640             mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7641             mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7642         }
7643
7644         // Let the policy update hidden states.
7645         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7646         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7647         config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7648         mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7649     }
7650
7651     void notifyHardKeyboardStatusChange() {
7652         final boolean available;
7653         final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
7654         synchronized (mWindowMap) {
7655             listener = mHardKeyboardStatusChangeListener;
7656             available = mHardKeyboardAvailable;
7657         }
7658         if (listener != null) {
7659             listener.onHardKeyboardStatusChange(available);
7660         }
7661     }
7662
7663     boolean startMovingTask(IWindow window, float startX, float startY) {
7664         WindowState win = null;
7665         synchronized (mWindowMap) {
7666             win = windowForClientLocked(null, window, false);
7667             // win shouldn't be null here, pass it down to startPositioningLocked
7668             // to get warning if it's null.
7669             if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
7670                 return false;
7671             }
7672         }
7673         try {
7674             mActivityManager.setFocusedTask(win.getTask().mTaskId);
7675         } catch(RemoteException e) {}
7676         return true;
7677     }
7678
7679     private void startScrollingTask(DisplayContent displayContent, int startX, int startY) {
7680         if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM,
7681                 "startScrollingTask: " + "{" + startX + ", " + startY + "}");
7682
7683         Task task = null;
7684         synchronized (mWindowMap) {
7685             int taskId = displayContent.taskIdFromPoint(startX, startY);
7686             if (taskId >= 0) {
7687                 task = mTaskIdToTask.get(taskId);
7688             }
7689             if (task == null || !task.isDockedInEffect() || !startPositioningLocked(
7690                     task.getTopVisibleAppMainWindow(), false /*resize*/, startX, startY)) {
7691                 return;
7692             }
7693         }
7694         try {
7695             mActivityManager.setFocusedTask(task.mTaskId);
7696         } catch(RemoteException e) {}
7697     }
7698
7699     private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
7700         int taskId = -1;
7701         synchronized (mWindowMap) {
7702             final Task task = displayContent.findTaskForControlPoint(x, y);
7703             if (task != null) {
7704                 if (!startPositioningLocked(
7705                         task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
7706                     return;
7707                 }
7708                 taskId = task.mTaskId;
7709             } else {
7710                 taskId = displayContent.taskIdFromPoint(x, y);
7711             }
7712         }
7713         if (taskId >= 0) {
7714             try {
7715                 mActivityManager.setFocusedTask(taskId);
7716             } catch(RemoteException e) {}
7717         }
7718     }
7719
7720     private boolean startPositioningLocked(
7721             WindowState win, boolean resize, float startX, float startY) {
7722         if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: "
7723             + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}");
7724
7725         if (win == null || win.getAppToken() == null) {
7726             Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
7727             return false;
7728         }
7729         if (win.mInputChannel == null) {
7730             Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
7731                     + " probably being removed");
7732             return false;
7733         }
7734
7735         final DisplayContent displayContent = win.getDisplayContent();
7736         if (displayContent == null) {
7737             Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
7738             return false;
7739         }
7740
7741         Display display = displayContent.getDisplay();
7742         mTaskPositioner = new TaskPositioner(this);
7743         mTaskPositioner.register(display);
7744         mInputMonitor.updateInputWindowsLw(true /*force*/);
7745
7746         // We need to grab the touch focus so that the touch events during the
7747         // resizing/scrolling are not sent to the app. 'win' is the main window
7748         // of the app, it may not have focus since there might be other windows
7749         // on top (eg. a dialog window).
7750         WindowState transferFocusFromWin = win;
7751         if (mCurrentFocus != null && mCurrentFocus != win
7752                 && mCurrentFocus.mAppToken == win.mAppToken) {
7753             transferFocusFromWin = mCurrentFocus;
7754         }
7755         if (!mInputManager.transferTouchFocus(
7756                 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
7757             Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
7758             mTaskPositioner.unregister();
7759             mTaskPositioner = null;
7760             mInputMonitor.updateInputWindowsLw(true /*force*/);
7761             return false;
7762         }
7763
7764         mTaskPositioner.startDragLocked(win, resize, startX, startY);
7765         return true;
7766     }
7767
7768     private void finishPositioning() {
7769         if (DEBUG_TASK_POSITIONING) {
7770             Slog.d(TAG_WM, "finishPositioning");
7771         }
7772         synchronized (mWindowMap) {
7773             if (mTaskPositioner != null) {
7774                 mTaskPositioner.unregister();
7775                 mTaskPositioner = null;
7776                 mInputMonitor.updateInputWindowsLw(true /*force*/);
7777             }
7778         }
7779     }
7780
7781     void adjustForImeIfNeeded(final DisplayContent displayContent) {
7782         final WindowState imeWin = mInputMethodWindow;
7783         final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
7784                 && !displayContent.mDividerControllerLocked.isImeHideRequested();
7785         final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
7786         final TaskStack imeTargetStack = getImeFocusStackLocked();
7787         final int imeDockSide = (dockVisible && imeTargetStack != null) ?
7788                 imeTargetStack.getDockSide() : DOCKED_INVALID;
7789         final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
7790         final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
7791         final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock();
7792         final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw();
7793         final boolean imeHeightChanged = imeVisible &&
7794                 imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor();
7795
7796         // The divider could be adjusted for IME position, or be thinner than usual,
7797         // or both. There are three possible cases:
7798         // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
7799         // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
7800         // - If IME is not visible, divider is not moved and is normal width.
7801
7802         if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
7803             final ArrayList<TaskStack> stacks = displayContent.getStacks();
7804             for (int i = stacks.size() - 1; i >= 0; --i) {
7805                 final TaskStack stack = stacks.get(i);
7806                 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
7807                 if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) {
7808                     stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
7809                 } else {
7810                     stack.resetAdjustedForIme(false);
7811                 }
7812             }
7813             displayContent.mDividerControllerLocked.setAdjustedForIme(
7814                     imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
7815         } else {
7816             final ArrayList<TaskStack> stacks = displayContent.getStacks();
7817             for (int i = stacks.size() - 1; i >= 0; --i) {
7818                 final TaskStack stack = stacks.get(i);
7819                 stack.resetAdjustedForIme(!dockVisible);
7820             }
7821             displayContent.mDividerControllerLocked.setAdjustedForIme(
7822                     false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
7823         }
7824     }
7825
7826     // -------------------------------------------------------------
7827     // Drag and drop
7828     // -------------------------------------------------------------
7829
7830     IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7831             int flags, int width, int height, Surface outSurface) {
7832         if (DEBUG_DRAG) {
7833             Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
7834                     + " flags=" + Integer.toHexString(flags) + " win=" + window
7835                     + " asbinder=" + window.asBinder());
7836         }
7837
7838         final int callerPid = Binder.getCallingPid();
7839         final int callerUid = Binder.getCallingUid();
7840         final long origId = Binder.clearCallingIdentity();
7841         IBinder token = null;
7842
7843         try {
7844             synchronized (mWindowMap) {
7845                 try {
7846                     if (mDragState == null) {
7847                         // TODO(multi-display): support other displays
7848                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
7849                         final Display display = displayContent.getDisplay();
7850
7851                         SurfaceControl surface = new SurfaceControl(session, "drag surface",
7852                                 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7853                         surface.setLayerStack(display.getLayerStack());
7854                         float alpha = 1;
7855                         if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
7856                             alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
7857                         }
7858                         surface.setAlpha(alpha);
7859
7860                         if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
7861                                 + surface + ": CREATE");
7862                         outSurface.copyFrom(surface);
7863                         final IBinder winBinder = window.asBinder();
7864                         token = new Binder();
7865                         mDragState = new DragState(this, token, surface, flags, winBinder);
7866                         mDragState.mPid = callerPid;
7867                         mDragState.mUid = callerUid;
7868                         mDragState.mOriginalAlpha = alpha;
7869                         token = mDragState.mToken = new Binder();
7870
7871                         // 5 second timeout for this window to actually begin the drag
7872                         mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7873                         Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7874                         mH.sendMessageDelayed(msg, 5000);
7875                     } else {
7876                         Slog.w(TAG_WM, "Drag already in progress");
7877                     }
7878                 } catch (OutOfResourcesException e) {
7879                     Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
7880                     if (mDragState != null) {
7881                         mDragState.reset();
7882                         mDragState = null;
7883                     }
7884                 }
7885             }
7886         } finally {
7887             Binder.restoreCallingIdentity(origId);
7888         }
7889
7890         return token;
7891     }
7892
7893     // -------------------------------------------------------------
7894     // Input Events and Focus Management
7895     // -------------------------------------------------------------
7896
7897     final InputMonitor mInputMonitor = new InputMonitor(this);
7898     private boolean mEventDispatchingEnabled;
7899
7900     @Override
7901     public void pauseKeyDispatching(IBinder _token) {
7902         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7903                 "pauseKeyDispatching()")) {
7904             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7905         }
7906
7907         synchronized (mWindowMap) {
7908             WindowToken token = mTokenMap.get(_token);
7909             if (token != null) {
7910                 mInputMonitor.pauseDispatchingLw(token);
7911             }
7912         }
7913     }
7914
7915     @Override
7916     public void resumeKeyDispatching(IBinder _token) {
7917         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7918                 "resumeKeyDispatching()")) {
7919             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7920         }
7921
7922         synchronized (mWindowMap) {
7923             WindowToken token = mTokenMap.get(_token);
7924             if (token != null) {
7925                 mInputMonitor.resumeDispatchingLw(token);
7926             }
7927         }
7928     }
7929
7930     @Override
7931     public void setEventDispatching(boolean enabled) {
7932         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7933                 "setEventDispatching()")) {
7934             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7935         }
7936
7937         synchronized (mWindowMap) {
7938             mEventDispatchingEnabled = enabled;
7939             if (mDisplayEnabled) {
7940                 mInputMonitor.setEventDispatchingLw(enabled);
7941             }
7942         }
7943     }
7944
7945     private WindowState getFocusedWindow() {
7946         synchronized (mWindowMap) {
7947             return getFocusedWindowLocked();
7948         }
7949     }
7950
7951     private WindowState getFocusedWindowLocked() {
7952         return mCurrentFocus;
7953     }
7954
7955     TaskStack getImeFocusStackLocked() {
7956         // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
7957         // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
7958         // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
7959         // to make room for IME, but the window is not the focused window that's taking input.
7960         return (mFocusedApp != null && mFocusedApp.mTask != null) ?
7961                 mFocusedApp.mTask.mStack : null;
7962     }
7963
7964     private void showAuditSafeModeNotification() {
7965         PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
7966                 new Intent(Intent.ACTION_VIEW,
7967                            Uri.parse("https://support.google.com/nexus/answer/2852139")), 0);
7968
7969         String title = mContext.getString(R.string.audit_safemode_notification);
7970
7971         Notification notification = new Notification.Builder(mContext)
7972                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
7973                 .setWhen(0)
7974                 .setOngoing(true)
7975                 .setTicker(title)
7976                 .setLocalOnly(true)
7977                 .setPriority(Notification.PRIORITY_HIGH)
7978                 .setVisibility(Notification.VISIBILITY_PUBLIC)
7979                 .setColor(mContext.getColor(
7980                         com.android.internal.R.color.system_notification_accent_color))
7981                 .setContentTitle(title)
7982                 .setContentText(mContext.getString(R.string.audit_safemode_notification_details))
7983                 .setContentIntent(pendingIntent)
7984                 .build();
7985
7986         NotificationManager notificationManager = (NotificationManager) mContext
7987                 .getSystemService(Context.NOTIFICATION_SERVICE);
7988
7989         notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification,
7990                 UserHandle.ALL);
7991     }
7992
7993     public boolean detectSafeMode() {
7994         if (!mInputMonitor.waitForInputDevicesReady(
7995                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7996             Slog.w(TAG_WM, "Devices still not ready after waiting "
7997                    + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7998                    + " milliseconds before attempting to detect safe mode.");
7999         }
8000
8001         if (Settings.Global.getInt(
8002                 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
8003             return false;
8004         }
8005
8006         int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
8007                 KeyEvent.KEYCODE_MENU);
8008         int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
8009         int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
8010                 KeyEvent.KEYCODE_DPAD_CENTER);
8011         int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
8012                 InputManagerService.BTN_MOUSE);
8013         int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
8014                 KeyEvent.KEYCODE_VOLUME_DOWN);
8015         mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
8016                 || volumeDownState > 0;
8017         try {
8018             if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
8019                     || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
8020                 int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0);
8021
8022                 if (auditSafeMode == 0) {
8023                     mSafeMode = true;
8024                     SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
8025                 } else {
8026                     // stay in safe mode until we have updated to a newer build
8027                     int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0);
8028
8029                     if (auditSafeMode >= buildDate) {
8030                         mSafeMode = true;
8031                         showAuditSafeModeNotification();
8032                     } else {
8033                         SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
8034                         SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, "");
8035                     }
8036                 }
8037             }
8038         } catch (IllegalArgumentException e) {
8039         }
8040         if (mSafeMode) {
8041             Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
8042                     + " dpad=" + dpadState + " trackball=" + trackballState + ")");
8043             SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
8044         } else {
8045             Log.i(TAG_WM, "SAFE MODE not enabled");
8046         }
8047         mPolicy.setSafeMode(mSafeMode);
8048         return mSafeMode;
8049     }
8050
8051     public void displayReady() {
8052         for (Display display : mDisplays) {
8053             displayReady(display.getDisplayId());
8054         }
8055
8056         synchronized(mWindowMap) {
8057             final DisplayContent displayContent = getDefaultDisplayContentLocked();
8058             readForcedDisplayPropertiesLocked(displayContent);
8059             mDisplayReady = true;
8060         }
8061
8062         try {
8063             mActivityManager.updateConfiguration(null);
8064         } catch (RemoteException e) {
8065         }
8066
8067         synchronized(mWindowMap) {
8068             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
8069                     PackageManager.FEATURE_TOUCHSCREEN);
8070             configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
8071         }
8072
8073         try {
8074             mActivityManager.updateConfiguration(null);
8075         } catch (RemoteException e) {
8076         }
8077
8078         updateCircularDisplayMaskIfNeeded();
8079     }
8080
8081     private void displayReady(int displayId) {
8082         synchronized(mWindowMap) {
8083             final DisplayContent displayContent = getDisplayContentLocked(displayId);
8084             if (displayContent != null) {
8085                 mAnimator.addDisplayLocked(displayId);
8086                 displayContent.initializeDisplayBaseInfo();
8087                 if (displayContent.mTapDetector != null) {
8088                     displayContent.mTapDetector.init();
8089                 }
8090             }
8091         }
8092     }
8093
8094     public void systemReady() {
8095         mPolicy.systemReady();
8096     }
8097
8098     // -------------------------------------------------------------
8099     // Async Handler
8100     // -------------------------------------------------------------
8101
8102     final class H extends Handler {
8103         public static final int REPORT_FOCUS_CHANGE = 2;
8104         public static final int REPORT_LOSING_FOCUS = 3;
8105         public static final int DO_TRAVERSAL = 4;
8106         public static final int ADD_STARTING = 5;
8107         public static final int REMOVE_STARTING = 6;
8108         public static final int FINISHED_STARTING = 7;
8109         public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
8110         public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
8111         public static final int WINDOW_FREEZE_TIMEOUT = 11;
8112
8113         public static final int APP_TRANSITION_TIMEOUT = 13;
8114         public static final int PERSIST_ANIMATION_SCALE = 14;
8115         public static final int FORCE_GC = 15;
8116         public static final int ENABLE_SCREEN = 16;
8117         public static final int APP_FREEZE_TIMEOUT = 17;
8118         public static final int SEND_NEW_CONFIGURATION = 18;
8119         public static final int REPORT_WINDOWS_CHANGE = 19;
8120         public static final int DRAG_START_TIMEOUT = 20;
8121         public static final int DRAG_END_TIMEOUT = 21;
8122         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
8123         public static final int BOOT_TIMEOUT = 23;
8124         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
8125         public static final int SHOW_STRICT_MODE_VIOLATION = 25;
8126         public static final int DO_ANIMATION_CALLBACK = 26;
8127
8128         public static final int DO_DISPLAY_ADDED = 27;
8129         public static final int DO_DISPLAY_REMOVED = 28;
8130         public static final int DO_DISPLAY_CHANGED = 29;
8131
8132         public static final int CLIENT_FREEZE_TIMEOUT = 30;
8133         public static final int TAP_OUTSIDE_TASK = 31;
8134         public static final int NOTIFY_ACTIVITY_DRAWN = 32;
8135
8136         public static final int ALL_WINDOWS_DRAWN = 33;
8137
8138         public static final int NEW_ANIMATOR_SCALE = 34;
8139
8140         public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
8141         public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
8142
8143         public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
8144         public static final int RESET_ANR_MESSAGE = 38;
8145         public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
8146
8147         public static final int FINISH_TASK_POSITIONING = 40;
8148
8149         public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
8150
8151         public static final int RESIZE_STACK = 42;
8152         public static final int RESIZE_TASK = 43;
8153
8154         public static final int TWO_FINGER_SCROLL_START = 44;
8155
8156         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
8157
8158         public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
8159         public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
8160         public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
8161         public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
8162         public static final int UPDATE_ANIMATION_SCALE = 51;
8163         public static final int WINDOW_REMOVE_TIMEOUT = 52;
8164         public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
8165         public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
8166
8167         /**
8168          * Used to denote that an integer field in a message will not be used.
8169          */
8170         public static final int UNUSED = 0;
8171
8172         @Override
8173         public void handleMessage(Message msg) {
8174             if (DEBUG_WINDOW_TRACE) {
8175                 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
8176             }
8177             switch (msg.what) {
8178                 case REPORT_FOCUS_CHANGE: {
8179                     WindowState lastFocus;
8180                     WindowState newFocus;
8181
8182                     AccessibilityController accessibilityController = null;
8183
8184                     synchronized(mWindowMap) {
8185                         // TODO(multidisplay): Accessibility supported only of default desiplay.
8186                         if (mAccessibilityController != null && getDefaultDisplayContentLocked()
8187                                 .getDisplayId() == Display.DEFAULT_DISPLAY) {
8188                             accessibilityController = mAccessibilityController;
8189                         }
8190
8191                         lastFocus = mLastFocus;
8192                         newFocus = mCurrentFocus;
8193                         if (lastFocus == newFocus) {
8194                             // Focus is not changing, so nothing to do.
8195                             return;
8196                         }
8197                         mLastFocus = newFocus;
8198                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
8199                                 " to " + newFocus);
8200                         if (newFocus != null && lastFocus != null
8201                                 && !newFocus.isDisplayedLw()) {
8202                             //Slog.i(TAG_WM, "Delaying loss of focus...");
8203                             mLosingFocus.add(lastFocus);
8204                             lastFocus = null;
8205                         }
8206                     }
8207
8208                     // First notify the accessibility manager for the change so it has
8209                     // the windows before the newly focused one starts firing eventgs.
8210                     if (accessibilityController != null) {
8211                         accessibilityController.onWindowFocusChangedNotLocked();
8212                     }
8213
8214                     //System.out.println("Changing focus from " + lastFocus
8215                     //                   + " to " + newFocus);
8216                     if (newFocus != null) {
8217                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
8218                         newFocus.reportFocusChangedSerialized(true, mInTouchMode);
8219                         notifyFocusChanged();
8220                     }
8221
8222                     if (lastFocus != null) {
8223                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
8224                         lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
8225                     }
8226                 } break;
8227
8228                 case REPORT_LOSING_FOCUS: {
8229                     ArrayList<WindowState> losers;
8230
8231                     synchronized(mWindowMap) {
8232                         losers = mLosingFocus;
8233                         mLosingFocus = new ArrayList<WindowState>();
8234                     }
8235
8236                     final int N = losers.size();
8237                     for (int i=0; i<N; i++) {
8238                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
8239                                 losers.get(i));
8240                         losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
8241                     }
8242                 } break;
8243
8244                 case DO_TRAVERSAL: {
8245                     synchronized(mWindowMap) {
8246                         mWindowPlacerLocked.performSurfacePlacement();
8247                     }
8248                 } break;
8249
8250                 case ADD_STARTING: {
8251                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8252                     final StartingData sd = wtoken.startingData;
8253
8254                     if (sd == null) {
8255                         // Animation has been canceled... do nothing.
8256                         return;
8257                     }
8258
8259                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
8260                             + wtoken + ": pkg=" + sd.pkg);
8261
8262                     View view = null;
8263                     try {
8264                         final Configuration overrideConfig = wtoken != null && wtoken.mTask != null
8265                                 ? wtoken.mTask.mOverrideConfig : null;
8266                         view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
8267                             sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
8268                             sd.windowFlags, overrideConfig);
8269                     } catch (Exception e) {
8270                         Slog.w(TAG_WM, "Exception when adding starting window", e);
8271                     }
8272
8273                     if (view != null) {
8274                         boolean abort = false;
8275
8276                         synchronized(mWindowMap) {
8277                             if (wtoken.removed || wtoken.startingData == null) {
8278                                 // If the window was successfully added, then
8279                                 // we need to remove it.
8280                                 if (wtoken.startingWindow != null) {
8281                                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
8282                                             "Aborted starting " + wtoken
8283                                             + ": removed=" + wtoken.removed
8284                                             + " startingData=" + wtoken.startingData);
8285                                     wtoken.startingWindow = null;
8286                                     wtoken.startingData = null;
8287                                     abort = true;
8288                                 }
8289                             } else {
8290                                 wtoken.startingView = view;
8291                             }
8292                             if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
8293                                     "Added starting " + wtoken
8294                                     + ": startingWindow="
8295                                     + wtoken.startingWindow + " startingView="
8296                                     + wtoken.startingView);
8297                         }
8298
8299                         if (abort) {
8300                             try {
8301                                 mPolicy.removeStartingWindow(wtoken.token, view);
8302                             } catch (Exception e) {
8303                                 Slog.w(TAG_WM, "Exception when removing starting window", e);
8304                             }
8305                         }
8306                     }
8307                 } break;
8308
8309                 case REMOVE_STARTING: {
8310                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8311                     IBinder token = null;
8312                     View view = null;
8313                     synchronized (mWindowMap) {
8314                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting "
8315                                 + wtoken + ": startingWindow="
8316                                 + wtoken.startingWindow + " startingView="
8317                                 + wtoken.startingView);
8318                         if (wtoken.startingWindow != null) {
8319                             view = wtoken.startingView;
8320                             token = wtoken.token;
8321                             wtoken.startingData = null;
8322                             wtoken.startingView = null;
8323                             wtoken.startingWindow = null;
8324                             wtoken.startingDisplayed = false;
8325                         }
8326                     }
8327                     if (view != null) {
8328                         try {
8329                             mPolicy.removeStartingWindow(token, view);
8330                         } catch (Exception e) {
8331                             Slog.w(TAG_WM, "Exception when removing starting window", e);
8332                         }
8333                     }
8334                 } break;
8335
8336                 case FINISHED_STARTING: {
8337                     IBinder token = null;
8338                     View view = null;
8339                     while (true) {
8340                         synchronized (mWindowMap) {
8341                             final int N = mFinishedStarting.size();
8342                             if (N <= 0) {
8343                                 break;
8344                             }
8345                             AppWindowToken wtoken = mFinishedStarting.remove(N-1);
8346
8347                             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
8348                                     "Finished starting " + wtoken
8349                                     + ": startingWindow=" + wtoken.startingWindow
8350                                     + " startingView=" + wtoken.startingView);
8351
8352                             if (wtoken.startingWindow == null) {
8353                                 continue;
8354                             }
8355
8356                             view = wtoken.startingView;
8357                             token = wtoken.token;
8358                             wtoken.startingData = null;
8359                             wtoken.startingView = null;
8360                             wtoken.startingWindow = null;
8361                             wtoken.startingDisplayed = false;
8362                         }
8363
8364                         try {
8365                             mPolicy.removeStartingWindow(token, view);
8366                         } catch (Exception e) {
8367                             Slog.w(TAG_WM, "Exception when removing starting window", e);
8368                         }
8369                     }
8370                 } break;
8371
8372                 case REPORT_APPLICATION_TOKEN_DRAWN: {
8373                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8374
8375                     try {
8376                         if (DEBUG_VISIBILITY) Slog.v(
8377                                 TAG_WM, "Reporting drawn in " + wtoken);
8378                         wtoken.appToken.windowsDrawn();
8379                     } catch (RemoteException ex) {
8380                     }
8381                 } break;
8382
8383                 case REPORT_APPLICATION_TOKEN_WINDOWS: {
8384                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8385
8386                     boolean nowVisible = msg.arg1 != 0;
8387                     boolean nowGone = msg.arg2 != 0;
8388
8389                     try {
8390                         if (DEBUG_VISIBILITY) Slog.v(
8391                                 TAG_WM, "Reporting visible in " + wtoken
8392                                 + " visible=" + nowVisible
8393                                 + " gone=" + nowGone);
8394                         if (nowVisible) {
8395                             wtoken.appToken.windowsVisible();
8396                         } else {
8397                             wtoken.appToken.windowsGone();
8398                         }
8399                     } catch (RemoteException ex) {
8400                     }
8401                 } break;
8402
8403                 case WINDOW_FREEZE_TIMEOUT: {
8404                     // TODO(multidisplay): Can non-default displays rotate?
8405                     synchronized (mWindowMap) {
8406                         Slog.w(TAG_WM, "Window freeze timeout expired.");
8407                         mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8408                         final WindowList windows = getDefaultWindowListLocked();
8409                         int i = windows.size();
8410                         while (i > 0) {
8411                             i--;
8412                             WindowState w = windows.get(i);
8413                             if (w.mOrientationChanging) {
8414                                 w.mOrientationChanging = false;
8415                                 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8416                                         - mDisplayFreezeTime);
8417                                 Slog.w(TAG_WM, "Force clearing orientation change: " + w);
8418                             }
8419                         }
8420                         mWindowPlacerLocked.performSurfacePlacement();
8421                     }
8422                     break;
8423                 }
8424
8425                 case APP_TRANSITION_TIMEOUT: {
8426                     synchronized (mWindowMap) {
8427                         if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
8428                                     || !mClosingApps.isEmpty()) {
8429                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
8430                                     + " isTransitionSet()=" + mAppTransition.isTransitionSet()
8431                                     + " mOpeningApps.size()=" + mOpeningApps.size()
8432                                     + " mClosingApps.size()=" + mClosingApps.size());
8433                             mAppTransition.setTimeout();
8434                             mWindowPlacerLocked.performSurfacePlacement();
8435                         }
8436                     }
8437                     break;
8438                 }
8439
8440                 case PERSIST_ANIMATION_SCALE: {
8441                     Settings.Global.putFloat(mContext.getContentResolver(),
8442                             Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
8443                     Settings.Global.putFloat(mContext.getContentResolver(),
8444                             Settings.Global.TRANSITION_ANIMATION_SCALE,
8445                             mTransitionAnimationScaleSetting);
8446                     Settings.Global.putFloat(mContext.getContentResolver(),
8447                             Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
8448                     break;
8449                 }
8450
8451                 case UPDATE_ANIMATION_SCALE: {
8452                     @UpdateAnimationScaleMode
8453                     final int mode = msg.arg1;
8454                     switch (mode) {
8455                         case WINDOW_ANIMATION_SCALE: {
8456                             mWindowAnimationScaleSetting = Settings.Global.getFloat(
8457                                     mContext.getContentResolver(),
8458                                     Settings.Global.WINDOW_ANIMATION_SCALE,
8459                                     mWindowAnimationScaleSetting);
8460                             break;
8461                         }
8462                         case TRANSITION_ANIMATION_SCALE: {
8463                             mTransitionAnimationScaleSetting = Settings.Global.getFloat(
8464                                     mContext.getContentResolver(),
8465                                     Settings.Global.TRANSITION_ANIMATION_SCALE,
8466                                     mTransitionAnimationScaleSetting);
8467                             break;
8468                         }
8469                         case ANIMATION_DURATION_SCALE: {
8470                             mAnimatorDurationScaleSetting = Settings.Global.getFloat(
8471                                     mContext.getContentResolver(),
8472                                     Settings.Global.ANIMATOR_DURATION_SCALE,
8473                                     mAnimatorDurationScaleSetting);
8474                             dispatchNewAnimatorScaleLocked(null);
8475                             break;
8476                         }
8477                     }
8478                     break;
8479                 }
8480
8481                 case FORCE_GC: {
8482                     synchronized (mWindowMap) {
8483                         // Since we're holding both mWindowMap and mAnimator we don't need to
8484                         // hold mAnimator.mLayoutToAnim.
8485                         if (mAnimator.isAnimating() || mAnimationScheduled) {
8486                             // If we are animating, don't do the gc now but
8487                             // delay a bit so we don't interrupt the animation.
8488                             sendEmptyMessageDelayed(H.FORCE_GC, 2000);
8489                             return;
8490                         }
8491                         // If we are currently rotating the display, it will
8492                         // schedule a new message when done.
8493                         if (mDisplayFrozen) {
8494                             return;
8495                         }
8496                     }
8497                     Runtime.getRuntime().gc();
8498                     break;
8499                 }
8500
8501                 case ENABLE_SCREEN: {
8502                     performEnableScreen();
8503                     break;
8504                 }
8505
8506                 case APP_FREEZE_TIMEOUT: {
8507                     synchronized (mWindowMap) {
8508                         Slog.w(TAG_WM, "App freeze timeout expired.");
8509                         mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8510                         final int numStacks = mStackIdToStack.size();
8511                         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8512                             final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
8513                             final ArrayList<Task> tasks = stack.getTasks();
8514                             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8515                                 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8516                                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8517                                     AppWindowToken tok = tokens.get(tokenNdx);
8518                                     if (tok.mAppAnimator.freezingScreen) {
8519                                         Slog.w(TAG_WM, "Force clearing freeze: " + tok);
8520                                         unsetAppFreezingScreenLocked(tok, true, true);
8521                                     }
8522                                 }
8523                             }
8524                         }
8525                     }
8526                     break;
8527                 }
8528
8529                 case CLIENT_FREEZE_TIMEOUT: {
8530                     synchronized (mWindowMap) {
8531                         if (mClientFreezingScreen) {
8532                             mClientFreezingScreen = false;
8533                             mLastFinishedFreezeSource = "client-timeout";
8534                             stopFreezingDisplayLocked();
8535                         }
8536                     }
8537                     break;
8538                 }
8539
8540                 case SEND_NEW_CONFIGURATION: {
8541                     removeMessages(SEND_NEW_CONFIGURATION);
8542                     sendNewConfiguration();
8543                     break;
8544                 }
8545
8546                 case REPORT_WINDOWS_CHANGE: {
8547                     if (mWindowsChanged) {
8548                         synchronized (mWindowMap) {
8549                             mWindowsChanged = false;
8550                         }
8551                         notifyWindowsChanged();
8552                     }
8553                     break;
8554                 }
8555
8556                 case DRAG_START_TIMEOUT: {
8557                     IBinder win = (IBinder)msg.obj;
8558                     if (DEBUG_DRAG) {
8559                         Slog.w(TAG_WM, "Timeout starting drag by win " + win);
8560                     }
8561                     synchronized (mWindowMap) {
8562                         // !!! TODO: ANR the app that has failed to start the drag in time
8563                         if (mDragState != null) {
8564                             mDragState.unregister();
8565                             mInputMonitor.updateInputWindowsLw(true /*force*/);
8566                             mDragState.reset();
8567                             mDragState = null;
8568                         }
8569                     }
8570                     break;
8571                 }
8572
8573                 case DRAG_END_TIMEOUT: {
8574                     IBinder win = (IBinder)msg.obj;
8575                     if (DEBUG_DRAG) {
8576                         Slog.w(TAG_WM, "Timeout ending drag to win " + win);
8577                     }
8578                     synchronized (mWindowMap) {
8579                         // !!! TODO: ANR the drag-receiving app
8580                         if (mDragState != null) {
8581                             mDragState.mDragResult = false;
8582                             mDragState.endDragLw();
8583                         }
8584                     }
8585                     break;
8586                 }
8587
8588                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
8589                     notifyHardKeyboardStatusChange();
8590                     break;
8591                 }
8592
8593                 case BOOT_TIMEOUT: {
8594                     performBootTimeout();
8595                     break;
8596                 }
8597
8598                 case WAITING_FOR_DRAWN_TIMEOUT: {
8599                     Runnable callback = null;
8600                     synchronized (mWindowMap) {
8601                         Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
8602                         mWaitingForDrawn.clear();
8603                         callback = mWaitingForDrawnCallback;
8604                         mWaitingForDrawnCallback = null;
8605                     }
8606                     if (callback != null) {
8607                         callback.run();
8608                     }
8609                     break;
8610                 }
8611
8612                 case SHOW_STRICT_MODE_VIOLATION: {
8613                     showStrictModeViolation(msg.arg1, msg.arg2);
8614                     break;
8615                 }
8616
8617                 case SHOW_CIRCULAR_DISPLAY_MASK: {
8618                     showCircularMask(msg.arg1 == 1);
8619                     break;
8620                 }
8621
8622                 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
8623                     showEmulatorDisplayOverlay();
8624                     break;
8625                 }
8626
8627                 case DO_ANIMATION_CALLBACK: {
8628                     try {
8629                         ((IRemoteCallback)msg.obj).sendResult(null);
8630                     } catch (RemoteException e) {
8631                     }
8632                     break;
8633                 }
8634
8635                 case DO_DISPLAY_ADDED:
8636                     handleDisplayAdded(msg.arg1);
8637                     break;
8638
8639                 case DO_DISPLAY_REMOVED:
8640                     synchronized (mWindowMap) {
8641                         handleDisplayRemovedLocked(msg.arg1);
8642                     }
8643                     break;
8644
8645                 case DO_DISPLAY_CHANGED:
8646                     synchronized (mWindowMap) {
8647                         handleDisplayChangedLocked(msg.arg1);
8648                     }
8649                     break;
8650
8651                 case TWO_FINGER_SCROLL_START: {
8652                     startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8653                 }
8654                 break;
8655
8656                 case TAP_OUTSIDE_TASK: {
8657                     handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8658                 }
8659                 break;
8660
8661                 case FINISH_TASK_POSITIONING: {
8662                     finishPositioning();
8663                 }
8664                 break;
8665
8666                 case NOTIFY_ACTIVITY_DRAWN:
8667                     try {
8668                         mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
8669                     } catch (RemoteException e) {
8670                     }
8671                     break;
8672                 case ALL_WINDOWS_DRAWN: {
8673                     Runnable callback;
8674                     synchronized (mWindowMap) {
8675                         callback = mWaitingForDrawnCallback;
8676                         mWaitingForDrawnCallback = null;
8677                     }
8678                     if (callback != null) {
8679                         callback.run();
8680                     }
8681                 }
8682                 case NEW_ANIMATOR_SCALE: {
8683                     float scale = getCurrentAnimatorScale();
8684                     ValueAnimator.setDurationScale(scale);
8685                     Session session = (Session)msg.obj;
8686                     if (session != null) {
8687                         try {
8688                             session.mCallback.onAnimatorScaleChanged(scale);
8689                         } catch (RemoteException e) {
8690                         }
8691                     } else {
8692                         ArrayList<IWindowSessionCallback> callbacks
8693                                 = new ArrayList<IWindowSessionCallback>();
8694                         synchronized (mWindowMap) {
8695                             for (int i=0; i<mSessions.size(); i++) {
8696                                 callbacks.add(mSessions.valueAt(i).mCallback);
8697                             }
8698
8699                         }
8700                         for (int i=0; i<callbacks.size(); i++) {
8701                             try {
8702                                 callbacks.get(i).onAnimatorScaleChanged(scale);
8703                             } catch (RemoteException e) {
8704                             }
8705                         }
8706                     }
8707                 }
8708                 break;
8709                 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
8710                     final boolean bootAnimationComplete;
8711                     synchronized (mWindowMap) {
8712                         if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
8713                         bootAnimationComplete = checkBootAnimationCompleteLocked();
8714                     }
8715                     if (bootAnimationComplete) {
8716                         performEnableScreen();
8717                     }
8718                 }
8719                 break;
8720                 case RESET_ANR_MESSAGE: {
8721                     synchronized (mWindowMap) {
8722                         mLastANRState = null;
8723                     }
8724                 }
8725                 break;
8726                 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
8727                     synchronized (mWindowMap) {
8728                         if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
8729                             mWindowPlacerLocked.performSurfacePlacement();
8730                         }
8731                     }
8732                 }
8733                 case UPDATE_DOCKED_STACK_DIVIDER: {
8734                     synchronized (mWindowMap) {
8735                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
8736                         displayContent.getDockedDividerController().reevaluateVisibility(false);
8737                         adjustForImeIfNeeded(displayContent);
8738                     }
8739                 }
8740                 break;
8741                 case RESIZE_TASK: {
8742                     try {
8743                         mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2);
8744                     } catch (RemoteException e) {
8745                         // This will not happen since we are in the same process.
8746                     }
8747                 }
8748                 break;
8749                 case RESIZE_STACK: {
8750                     try {
8751                         mActivityManager.resizeStack(
8752                                 msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1);
8753                     } catch (RemoteException e) {
8754                         // This will not happen since we are in the same process.
8755                     }
8756                 }
8757                 break;
8758                 case WINDOW_REPLACEMENT_TIMEOUT: {
8759                     synchronized (mWindowMap) {
8760                         for (int i = mReplacingWindowTimeouts.size() - 1; i >= 0; i--) {
8761                             final AppWindowToken token = mReplacingWindowTimeouts.get(i);
8762                             token.clearTimedoutReplacesLocked();
8763                         }
8764                         mReplacingWindowTimeouts.clear();
8765                     }
8766                 }
8767                 case NOTIFY_APP_TRANSITION_STARTING: {
8768                     mAmInternal.notifyAppTransitionStarting(msg.arg1);
8769                 }
8770                 break;
8771                 case NOTIFY_APP_TRANSITION_CANCELLED: {
8772                     mAmInternal.notifyAppTransitionCancelled();
8773                 }
8774                 break;
8775                 case NOTIFY_APP_TRANSITION_FINISHED: {
8776                     mAmInternal.notifyAppTransitionFinished();
8777                 }
8778                 break;
8779                 case NOTIFY_STARTING_WINDOW_DRAWN: {
8780                     mAmInternal.notifyStartingWindowDrawn();
8781                 }
8782                 break;
8783                 case WINDOW_REMOVE_TIMEOUT: {
8784                     final WindowState window = (WindowState) msg.obj;
8785                     synchronized(mWindowMap) {
8786                         // TODO: This is all about fixing b/21693547
8787                         // where partially initialized Toasts get stuck
8788                         // around and keep the screen on. We'd like
8789                         // to just remove the toast...but this can cause clients
8790                         // who miss the timeout due to normal circumstances (e.g.
8791                         // running under debugger) to crash (b/29105388). The windows will
8792                         // eventually be removed when the client process finishes.
8793                         // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
8794                         // and prevent the symptoms of b/21693547.
8795                         window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
8796                         window.setDisplayLayoutNeeded();
8797                         mWindowPlacerLocked.performSurfacePlacement();
8798                     }
8799                 }
8800                 break;
8801                 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
8802                     mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
8803                 }
8804                 break;
8805                 case SEAMLESS_ROTATION_TIMEOUT: {
8806                     // Rotation only supported on primary display.
8807                     // TODO(multi-display)
8808                     synchronized(mWindowMap) {
8809                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
8810                         final WindowList windows = displayContent.getWindowList();
8811                         boolean layoutNeeded = false;
8812                         for (int i = windows.size() - 1; i >= 0; i--) {
8813                             WindowState w = windows.get(i);
8814                             if (w.mSeamlesslyRotated) {
8815                                 layoutNeeded = true;
8816                                 w.setDisplayLayoutNeeded();
8817                             }
8818                             w.mSeamlesslyRotated = false;
8819                         }
8820                         if (layoutNeeded) {
8821                             mWindowPlacerLocked.performSurfacePlacement();
8822                         }
8823                     }
8824                 }
8825                 break;
8826             }
8827             if (DEBUG_WINDOW_TRACE) {
8828                 Slog.v(TAG_WM, "handleMessage: exit");
8829             }
8830         }
8831     }
8832
8833     void destroyPreservedSurfaceLocked() {
8834         for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
8835             final WindowState w = mDestroyPreservedSurface.get(i);
8836             w.mWinAnimator.destroyPreservedSurfaceLocked();
8837         }
8838         mDestroyPreservedSurface.clear();
8839     }
8840
8841     void stopUsingSavedSurfaceLocked() {
8842         for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
8843             final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
8844             wtoken.stopUsingSavedSurfaceLocked();
8845         }
8846         mFinishedEarlyAnim.clear();
8847     }
8848
8849     // -------------------------------------------------------------
8850     // IWindowManager API
8851     // -------------------------------------------------------------
8852
8853     @Override
8854     public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
8855             IInputContext inputContext) {
8856         if (client == null) throw new IllegalArgumentException("null client");
8857         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8858         Session session = new Session(this, callback, client, inputContext);
8859         return session;
8860     }
8861
8862     @Override
8863     public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8864         synchronized (mWindowMap) {
8865             // The focus for the client is the window immediately below
8866             // where we would place the input method window.
8867             int idx = findDesiredInputMethodWindowIndexLocked(false);
8868             if (idx > 0) {
8869                 // TODO(multidisplay): IMEs are only supported on the default display.
8870                 WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
8871                 if (DEBUG_INPUT_METHOD) {
8872                     Slog.i(TAG_WM, "Desired input method target: " + imFocus);
8873                     Slog.i(TAG_WM, "Current focus: " + mCurrentFocus);
8874                     Slog.i(TAG_WM, "Last focus: " + mLastFocus);
8875                 }
8876                 if (imFocus != null) {
8877                     // This may be a starting window, in which case we still want
8878                     // to count it as okay.
8879                     if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
8880                             && imFocus.mAppToken != null) {
8881                         // The client has definitely started, so it really should
8882                         // have a window in this app token.  Let's look for it.
8883                         for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
8884                             WindowState w = imFocus.mAppToken.windows.get(i);
8885                             if (w != imFocus) {
8886                                 Log.i(TAG_WM, "Switching to real app window: " + w);
8887                                 imFocus = w;
8888                                 break;
8889                             }
8890                         }
8891                     }
8892                     if (DEBUG_INPUT_METHOD) {
8893                         Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient);
8894                         if (imFocus.mSession.mClient != null) {
8895                             Slog.i(TAG_WM, "IM target client binder: "
8896                                     + imFocus.mSession.mClient.asBinder());
8897                             Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
8898                         }
8899                     }
8900                     if (imFocus.mSession.mClient != null &&
8901                             imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8902                         return true;
8903                     }
8904                 }
8905             }
8906
8907             // Okay, how about this...  what is the current focus?
8908             // It seems in some cases we may not have moved the IM
8909             // target window, such as when it was in a pop-up window,
8910             // so let's also look at the current focus.  (An example:
8911             // go to Gmail, start searching so the keyboard goes up,
8912             // press home.  Sometimes the IME won't go down.)
8913             // Would be nice to fix this more correctly, but it's
8914             // way at the end of a release, and this should be good enough.
8915             if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
8916                     && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
8917                 return true;
8918             }
8919         }
8920         return false;
8921     }
8922
8923     @Override
8924     public void getInitialDisplaySize(int displayId, Point size) {
8925         synchronized (mWindowMap) {
8926             final DisplayContent displayContent = getDisplayContentLocked(displayId);
8927             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8928                 size.x = displayContent.mInitialDisplayWidth;
8929                 size.y = displayContent.mInitialDisplayHeight;
8930             }
8931         }
8932     }
8933
8934     @Override
8935     public void getBaseDisplaySize(int displayId, Point size) {
8936         synchronized (mWindowMap) {
8937             final DisplayContent displayContent = getDisplayContentLocked(displayId);
8938             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8939                 size.x = displayContent.mBaseDisplayWidth;
8940                 size.y = displayContent.mBaseDisplayHeight;
8941             }
8942         }
8943     }
8944
8945     @Override
8946     public void setForcedDisplaySize(int displayId, int width, int height) {
8947         if (mContext.checkCallingOrSelfPermission(
8948                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8949                 PackageManager.PERMISSION_GRANTED) {
8950             throw new SecurityException("Must hold permission " +
8951                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
8952         }
8953         if (displayId != Display.DEFAULT_DISPLAY) {
8954             throw new IllegalArgumentException("Can only set the default display");
8955         }
8956         final long ident = Binder.clearCallingIdentity();
8957         try {
8958             synchronized(mWindowMap) {
8959                 // Set some sort of reasonable bounds on the size of the display that we
8960                 // will try to emulate.
8961                 final int MIN_WIDTH = 200;
8962                 final int MIN_HEIGHT = 200;
8963                 final int MAX_SCALE = 2;
8964                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8965                 if (displayContent != null) {
8966                     width = Math.min(Math.max(width, MIN_WIDTH),
8967                             displayContent.mInitialDisplayWidth * MAX_SCALE);
8968                     height = Math.min(Math.max(height, MIN_HEIGHT),
8969                             displayContent.mInitialDisplayHeight * MAX_SCALE);
8970                     setForcedDisplaySizeLocked(displayContent, width, height);
8971                     Settings.Global.putString(mContext.getContentResolver(),
8972                             Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
8973                 }
8974             }
8975         } finally {
8976             Binder.restoreCallingIdentity(ident);
8977         }
8978     }
8979
8980     @Override
8981     public void setForcedDisplayScalingMode(int displayId, int mode) {
8982         if (mContext.checkCallingOrSelfPermission(
8983                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8984                 PackageManager.PERMISSION_GRANTED) {
8985             throw new SecurityException("Must hold permission " +
8986                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
8987         }
8988         if (displayId != Display.DEFAULT_DISPLAY) {
8989             throw new IllegalArgumentException("Can only set the default display");
8990         }
8991         final long ident = Binder.clearCallingIdentity();
8992         try {
8993             synchronized(mWindowMap) {
8994                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8995                 if (displayContent != null) {
8996                     if (mode < 0 || mode > 1) {
8997                         mode = 0;
8998                     }
8999                     setForcedDisplayScalingModeLocked(displayContent, mode);
9000                     Settings.Global.putInt(mContext.getContentResolver(),
9001                             Settings.Global.DISPLAY_SCALING_FORCE, mode);
9002                 }
9003             }
9004         } finally {
9005             Binder.restoreCallingIdentity(ident);
9006         }
9007     }
9008
9009     private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
9010         Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
9011         displayContent.mDisplayScalingDisabled = (mode != 0);
9012         reconfigureDisplayLocked(displayContent);
9013     }
9014
9015     private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
9016         // Display size.
9017         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
9018                 Settings.Global.DISPLAY_SIZE_FORCED);
9019         if (sizeStr == null || sizeStr.length() == 0) {
9020             sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
9021         }
9022         if (sizeStr != null && sizeStr.length() > 0) {
9023             final int pos = sizeStr.indexOf(',');
9024             if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
9025                 int width, height;
9026                 try {
9027                     width = Integer.parseInt(sizeStr.substring(0, pos));
9028                     height = Integer.parseInt(sizeStr.substring(pos+1));
9029                     if (displayContent.mBaseDisplayWidth != width
9030                             || displayContent.mBaseDisplayHeight != height) {
9031                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
9032                         displayContent.mBaseDisplayWidth = width;
9033                         displayContent.mBaseDisplayHeight = height;
9034                     }
9035                 } catch (NumberFormatException ex) {
9036                 }
9037             }
9038         }
9039
9040         // Display density.
9041         final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
9042         if (density != 0) {
9043             displayContent.mBaseDisplayDensity = density;
9044         }
9045
9046         // Display scaling mode.
9047         int mode = Settings.Global.getInt(mContext.getContentResolver(),
9048                 Settings.Global.DISPLAY_SCALING_FORCE, 0);
9049         if (mode != 0) {
9050             Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
9051             displayContent.mDisplayScalingDisabled = true;
9052         }
9053     }
9054
9055     // displayContent must not be null
9056     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
9057         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
9058         displayContent.mBaseDisplayWidth = width;
9059         displayContent.mBaseDisplayHeight = height;
9060         reconfigureDisplayLocked(displayContent);
9061     }
9062
9063     @Override
9064     public void clearForcedDisplaySize(int displayId) {
9065         if (mContext.checkCallingOrSelfPermission(
9066                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9067                 PackageManager.PERMISSION_GRANTED) {
9068             throw new SecurityException("Must hold permission " +
9069                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
9070         }
9071         if (displayId != Display.DEFAULT_DISPLAY) {
9072             throw new IllegalArgumentException("Can only set the default display");
9073         }
9074         final long ident = Binder.clearCallingIdentity();
9075         try {
9076             synchronized(mWindowMap) {
9077                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9078                 if (displayContent != null) {
9079                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
9080                             displayContent.mInitialDisplayHeight);
9081                     Settings.Global.putString(mContext.getContentResolver(),
9082                             Settings.Global.DISPLAY_SIZE_FORCED, "");
9083                 }
9084             }
9085         } finally {
9086             Binder.restoreCallingIdentity(ident);
9087         }
9088     }
9089
9090     @Override
9091     public int getInitialDisplayDensity(int displayId) {
9092         synchronized (mWindowMap) {
9093             final DisplayContent displayContent = getDisplayContentLocked(displayId);
9094             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
9095                 return displayContent.mInitialDisplayDensity;
9096             }
9097         }
9098         return -1;
9099     }
9100
9101     @Override
9102     public int getBaseDisplayDensity(int displayId) {
9103         synchronized (mWindowMap) {
9104             final DisplayContent displayContent = getDisplayContentLocked(displayId);
9105             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
9106                 return displayContent.mBaseDisplayDensity;
9107             }
9108         }
9109         return -1;
9110     }
9111
9112     @Override
9113     public void setForcedDisplayDensity(int displayId, int density) {
9114         if (mContext.checkCallingOrSelfPermission(
9115                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9116                 PackageManager.PERMISSION_GRANTED) {
9117             throw new SecurityException("Must hold permission " +
9118                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
9119         }
9120         if (displayId != Display.DEFAULT_DISPLAY) {
9121             throw new IllegalArgumentException("Can only set the default display");
9122         }
9123         final long ident = Binder.clearCallingIdentity();
9124         try {
9125             synchronized(mWindowMap) {
9126                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9127                 if (displayContent != null) {
9128                     setForcedDisplayDensityLocked(displayContent, density);
9129                     Settings.Secure.putStringForUser(mContext.getContentResolver(),
9130                             Settings.Secure.DISPLAY_DENSITY_FORCED,
9131                             Integer.toString(density), mCurrentUserId);
9132                 }
9133             }
9134         } finally {
9135             Binder.restoreCallingIdentity(ident);
9136         }
9137     }
9138
9139     @Override
9140     public void clearForcedDisplayDensity(int displayId) {
9141         if (mContext.checkCallingOrSelfPermission(
9142                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9143                 PackageManager.PERMISSION_GRANTED) {
9144             throw new SecurityException("Must hold permission " +
9145                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
9146         }
9147         if (displayId != Display.DEFAULT_DISPLAY) {
9148             throw new IllegalArgumentException("Can only set the default display");
9149         }
9150         final long ident = Binder.clearCallingIdentity();
9151         try {
9152             synchronized(mWindowMap) {
9153                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9154                 if (displayContent != null) {
9155                     setForcedDisplayDensityLocked(displayContent,
9156                             displayContent.mInitialDisplayDensity);
9157                     Settings.Secure.putStringForUser(mContext.getContentResolver(),
9158                             Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId);
9159                 }
9160             }
9161         } finally {
9162             Binder.restoreCallingIdentity(ident);
9163         }
9164     }
9165
9166     /**
9167      * @param userId the ID of the user
9168      * @return the forced display density for the specified user, if set, or
9169      *         {@code 0} if not set
9170      */
9171     private int getForcedDisplayDensityForUserLocked(int userId) {
9172         String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
9173                 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
9174         if (densityStr == null || densityStr.length() == 0) {
9175             densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
9176         }
9177         if (densityStr != null && densityStr.length() > 0) {
9178             try {
9179                 return Integer.parseInt(densityStr);
9180             } catch (NumberFormatException ex) {
9181             }
9182         }
9183         return 0;
9184     }
9185
9186     /**
9187      * Forces the given display to the use the specified density.
9188      *
9189      * @param displayContent the display to modify
9190      * @param density the density in DPI to use
9191      */
9192     private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
9193             int density) {
9194         displayContent.mBaseDisplayDensity = density;
9195         reconfigureDisplayLocked(displayContent);
9196     }
9197
9198     // displayContent must not be null
9199     private void reconfigureDisplayLocked(DisplayContent displayContent) {
9200         // TODO: Multidisplay: for now only use with default display.
9201         if (!mDisplayReady) {
9202             return;
9203         }
9204         configureDisplayPolicyLocked(displayContent);
9205         displayContent.layoutNeeded = true;
9206
9207         boolean configChanged = updateOrientationFromAppTokensLocked(false);
9208         mTempConfiguration.setToDefaults();
9209         mTempConfiguration.updateFrom(mCurConfiguration);
9210         computeScreenConfigurationLocked(mTempConfiguration);
9211         configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
9212
9213         if (configChanged) {
9214             mWaitingForConfig = true;
9215             startFreezingDisplayLocked(false, 0, 0);
9216             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9217             if (!mReconfigureOnConfigurationChanged.contains(displayContent)) {
9218                 mReconfigureOnConfigurationChanged.add(displayContent);
9219             }
9220         }
9221
9222         mWindowPlacerLocked.performSurfacePlacement();
9223     }
9224
9225     private void configureDisplayPolicyLocked(DisplayContent displayContent) {
9226         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
9227                 displayContent.mBaseDisplayWidth,
9228                 displayContent.mBaseDisplayHeight,
9229                 displayContent.mBaseDisplayDensity);
9230
9231         DisplayInfo displayInfo = displayContent.getDisplayInfo();
9232         mPolicy.setDisplayOverscan(displayContent.getDisplay(),
9233                 displayInfo.overscanLeft, displayInfo.overscanTop,
9234                 displayInfo.overscanRight, displayInfo.overscanBottom);
9235     }
9236
9237     @Override
9238     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
9239         if (mContext.checkCallingOrSelfPermission(
9240                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9241                 PackageManager.PERMISSION_GRANTED) {
9242             throw new SecurityException("Must hold permission " +
9243                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
9244         }
9245         final long ident = Binder.clearCallingIdentity();
9246         try {
9247             synchronized(mWindowMap) {
9248                 DisplayContent displayContent = getDisplayContentLocked(displayId);
9249                 if (displayContent != null) {
9250                     setOverscanLocked(displayContent, left, top, right, bottom);
9251                 }
9252             }
9253         } finally {
9254             Binder.restoreCallingIdentity(ident);
9255         }
9256     }
9257
9258     private void setOverscanLocked(DisplayContent displayContent,
9259             int left, int top, int right, int bottom) {
9260         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
9261         displayInfo.overscanLeft = left;
9262         displayInfo.overscanTop = top;
9263         displayInfo.overscanRight = right;
9264         displayInfo.overscanBottom = bottom;
9265
9266         mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
9267                 right, bottom);
9268         mDisplaySettings.writeSettingsLocked();
9269
9270         reconfigureDisplayLocked(displayContent);
9271     }
9272
9273     // -------------------------------------------------------------
9274     // Internals
9275     // -------------------------------------------------------------
9276
9277     final WindowState windowForClientLocked(Session session, IWindow client,
9278             boolean throwOnError) {
9279         return windowForClientLocked(session, client.asBinder(), throwOnError);
9280     }
9281
9282     final WindowState windowForClientLocked(Session session, IBinder client,
9283             boolean throwOnError) {
9284         WindowState win = mWindowMap.get(client);
9285         if (localLOGV) Slog.v(
9286             TAG_WM, "Looking up client " + client + ": " + win);
9287         if (win == null) {
9288             RuntimeException ex = new IllegalArgumentException(
9289                     "Requested window " + client + " does not exist");
9290             if (throwOnError) {
9291                 throw ex;
9292             }
9293             Slog.w(TAG_WM, "Failed looking up window", ex);
9294             return null;
9295         }
9296         if (session != null && win.mSession != session) {
9297             RuntimeException ex = new IllegalArgumentException(
9298                     "Requested window " + client + " is in session " +
9299                     win.mSession + ", not " + session);
9300             if (throwOnError) {
9301                 throw ex;
9302             }
9303             Slog.w(TAG_WM, "Failed looking up window", ex);
9304             return null;
9305         }
9306
9307         return win;
9308     }
9309
9310     final void rebuildAppWindowListLocked() {
9311         rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
9312     }
9313
9314     private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
9315         final WindowList windows = displayContent.getWindowList();
9316         int NW = windows.size();
9317         int i;
9318         int lastBelow = -1;
9319         int numRemoved = 0;
9320
9321         if (mRebuildTmp.length < NW) {
9322             mRebuildTmp = new WindowState[NW+10];
9323         }
9324
9325         // First remove all existing app windows.
9326         i=0;
9327         while (i < NW) {
9328             WindowState w = windows.get(i);
9329             if (w.mAppToken != null) {
9330                 WindowState win = windows.remove(i);
9331                 win.mRebuilding = true;
9332                 mRebuildTmp[numRemoved] = win;
9333                 mWindowsChanged = true;
9334                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
9335                 NW--;
9336                 numRemoved++;
9337                 continue;
9338             } else if (lastBelow == i-1) {
9339                 if (w.mAttrs.type == TYPE_WALLPAPER) {
9340                     lastBelow = i;
9341                 }
9342             }
9343             i++;
9344         }
9345
9346         // Keep whatever windows were below the app windows still below,
9347         // by skipping them.
9348         lastBelow++;
9349         i = lastBelow;
9350
9351         // First add all of the exiting app tokens...  these are no longer
9352         // in the main app list, but still have windows shown.  We put them
9353         // in the back because now that the animation is over we no longer
9354         // will care about them.
9355         final ArrayList<TaskStack> stacks = displayContent.getStacks();
9356         final int numStacks = stacks.size();
9357         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
9358             AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
9359             int NT = exitingAppTokens.size();
9360             for (int j = 0; j < NT; j++) {
9361                 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
9362             }
9363         }
9364
9365         // And add in the still active app tokens in Z order.
9366         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
9367             final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9368             final int numTasks = tasks.size();
9369             for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
9370                 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9371                 final int numTokens = tokens.size();
9372                 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
9373                     final AppWindowToken wtoken = tokens.get(tokenNdx);
9374                     if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) {
9375                         continue;
9376                     }
9377                     i = reAddAppWindowsLocked(displayContent, i, wtoken);
9378                 }
9379             }
9380         }
9381
9382         i -= lastBelow;
9383         if (i != numRemoved) {
9384             displayContent.layoutNeeded = true;
9385             Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
9386                     + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
9387                     + " callers=" + Debug.getCallers(10));
9388             for (i = 0; i < numRemoved; i++) {
9389                 WindowState ws = mRebuildTmp[i];
9390                 if (ws.mRebuilding) {
9391                     StringWriter sw = new StringWriter();
9392                     PrintWriter pw = new FastPrintWriter(sw, false, 1024);
9393                     ws.dump(pw, "", true);
9394                     pw.flush();
9395                     Slog.w(TAG_WM, "This window was lost: " + ws);
9396                     Slog.w(TAG_WM, sw.toString());
9397                     ws.mWinAnimator.destroySurfaceLocked();
9398                 }
9399             }
9400             Slog.w(TAG_WM, "Current app token list:");
9401             dumpAppTokensLocked();
9402             Slog.w(TAG_WM, "Final window list:");
9403             dumpWindowsLocked();
9404         }
9405         Arrays.fill(mRebuildTmp, null);
9406     }
9407
9408     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
9409         // If the screen is currently frozen or off, then keep
9410         // it frozen/off until this window draws at its new
9411         // orientation.
9412         if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
9413             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
9414             w.mOrientationChanging = true;
9415             w.mLastFreezeDuration = 0;
9416             mWindowPlacerLocked.mOrientationChangeComplete = false;
9417             if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
9418                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
9419                 // XXX should probably keep timeout from
9420                 // when we first froze the display.
9421                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9422                 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
9423                         WINDOW_FREEZE_TIMEOUT_DURATION);
9424             }
9425         }
9426     }
9427
9428     /**
9429      * @return bitmap indicating if another pass through layout must be made.
9430      */
9431     int handleAnimatingStoppedAndTransitionLocked() {
9432         int changes = 0;
9433
9434         mAppTransition.setIdle();
9435
9436         for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
9437             final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
9438             mAppTransition.notifyAppTransitionFinishedLocked(token);
9439         }
9440         mNoAnimationNotifyOnTransitionFinished.clear();
9441
9442         mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
9443
9444         // Restore window app tokens to the ActivityManager views
9445         ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9446         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9447             final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9448             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9449                 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9450                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9451                     tokens.get(tokenNdx).sendingToBottom = false;
9452                 }
9453             }
9454         }
9455         rebuildAppWindowListLocked();
9456
9457         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9458         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
9459                 "Wallpaper layer changed: assigning layers + relayout");
9460         moveInputMethodWindowsIfNeededLocked(true);
9461         mWindowPlacerLocked.mWallpaperMayChange = true;
9462         // Since the window list has been rebuilt, focus might
9463         // have to be recomputed since the actual order of windows
9464         // might have changed again.
9465         mFocusMayChange = true;
9466
9467         return changes;
9468     }
9469
9470     void updateResizingWindows(final WindowState w) {
9471         final WindowStateAnimator winAnimator = w.mWinAnimator;
9472         if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) {
9473             final Task task = w.getTask();
9474             // In the case of stack bound animations, the window frames
9475             // will update (unlike other animations which just modifiy
9476             // various transformation properties). We don't want to
9477             // notify the client of frame changes in this case. Not only
9478             // is it a lot of churn, but the frame may not correspond
9479             // to the surface size or the onscreen area at various
9480             // phases in the animation, and the client will become
9481             // sad and confused.
9482             if (task != null && task.mStack.getBoundsAnimating()) {
9483                 return;
9484             }
9485             w.setReportResizeHints();
9486             boolean configChanged = w.isConfigChanged();
9487             if (DEBUG_CONFIGURATION && configChanged) {
9488                 Slog.v(TAG_WM, "Win " + w + " config changed: "
9489                         + mCurConfiguration);
9490             }
9491             final boolean dragResizingChanged = w.isDragResizeChanged()
9492                     && !w.isDragResizingChangeReported();
9493
9494             if (localLOGV) Slog.v(TAG_WM, "Resizing " + w
9495                     + ": configChanged=" + configChanged
9496                     + " dragResizingChanged=" + dragResizingChanged
9497                     + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9498
9499             // We update mLastFrame always rather than in the conditional with the
9500             // last inset variables, because mFrameSizeChanged only tracks the
9501             // width and height changing.
9502             w.mLastFrame.set(w.mFrame);
9503
9504             if (w.mContentInsetsChanged
9505                     || w.mVisibleInsetsChanged
9506                     || winAnimator.mSurfaceResized
9507                     || w.mOutsetsChanged
9508                     || w.mFrameSizeChanged
9509                     || configChanged
9510                     || dragResizingChanged
9511                     || !w.isResizedWhileNotDragResizingReported()) {
9512                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9513                     Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
9514                             + " contentInsetsChanged=" + w.mContentInsetsChanged
9515                             + " " + w.mContentInsets.toShortString()
9516                             + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9517                             + " " + w.mVisibleInsets.toShortString()
9518                             + " stableInsetsChanged=" + w.mStableInsetsChanged
9519                             + " " + w.mStableInsets.toShortString()
9520                             + " outsetsChanged=" + w.mOutsetsChanged
9521                             + " " + w.mOutsets.toShortString()
9522                             + " surfaceResized=" + winAnimator.mSurfaceResized
9523                             + " configChanged=" + configChanged
9524                             + " dragResizingChanged=" + dragResizingChanged
9525                             + " resizedWhileNotDragResizingReported="
9526                             + w.isResizedWhileNotDragResizingReported());
9527                 }
9528
9529                 // If it's a dead window left on screen, and the configuration changed,
9530                 // there is nothing we can do about it. Remove the window now.
9531                 if (w.mAppToken != null && w.mAppDied) {
9532                     w.mAppToken.removeAllDeadWindows();
9533                     return;
9534                 }
9535
9536                 w.mLastOverscanInsets.set(w.mOverscanInsets);
9537                 w.mLastContentInsets.set(w.mContentInsets);
9538                 w.mLastVisibleInsets.set(w.mVisibleInsets);
9539                 w.mLastStableInsets.set(w.mStableInsets);
9540                 w.mLastOutsets.set(w.mOutsets);
9541                 makeWindowFreezingScreenIfNeededLocked(w);
9542                 // If the orientation is changing, or we're starting or ending
9543                 // a drag resizing action, then we need to hold off on unfreezing
9544                 // the display until this window has been redrawn; to do that,
9545                 // we need to go through the process of getting informed by the
9546                 // application when it has finished drawing.
9547                 if (w.mOrientationChanging || dragResizingChanged
9548                         || w.isResizedWhileNotDragResizing()) {
9549                     if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
9550                         Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
9551                                 + ", mDrawState=DRAW_PENDING in " + w
9552                                 + ", surfaceController " + winAnimator.mSurfaceController);
9553                     }
9554                     winAnimator.mDrawState = DRAW_PENDING;
9555                     if (w.mAppToken != null) {
9556                         w.mAppToken.clearAllDrawn();
9557                     }
9558                 }
9559                 if (!mResizingWindows.contains(w)) {
9560                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM,
9561                             "Resizing window " + w);
9562                     mResizingWindows.add(w);
9563                 }
9564             } else if (w.mOrientationChanging) {
9565                 if (w.isDrawnLw()) {
9566                     if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
9567                             "Orientation not waiting for draw in "
9568                             + w + ", surfaceController " + winAnimator.mSurfaceController);
9569                     w.mOrientationChanging = false;
9570                     w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9571                             - mDisplayFreezeTime);
9572                 }
9573             }
9574         }
9575     }
9576
9577     void checkDrawnWindowsLocked() {
9578         if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9579             return;
9580         }
9581         for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9582             WindowState win = mWaitingForDrawn.get(j);
9583             if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
9584                     ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9585                     " mHasSurface=" + win.mHasSurface +
9586                     " drawState=" + win.mWinAnimator.mDrawState);
9587             if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
9588                 // Window has been removed or hidden; no draw will now happen, so stop waiting.
9589                 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
9590                 mWaitingForDrawn.remove(win);
9591             } else if (win.hasDrawnLw()) {
9592                 // Window is now drawn (and shown).
9593                 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
9594                 mWaitingForDrawn.remove(win);
9595             }
9596         }
9597         if (mWaitingForDrawn.isEmpty()) {
9598             if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
9599             mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9600             mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9601         }
9602     }
9603
9604     void setHoldScreenLocked(final Session newHoldScreen) {
9605         final boolean hold = newHoldScreen != null;
9606
9607         if (hold && mHoldingScreenOn != newHoldScreen) {
9608             mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9609         }
9610         mHoldingScreenOn = newHoldScreen;
9611
9612         final boolean state = mHoldingScreenWakeLock.isHeld();
9613         if (hold != state) {
9614             if (hold) {
9615                 if (DEBUG_KEEP_SCREEN_ON) {
9616                     Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " +
9617                             mWindowPlacerLocked.mHoldScreenWindow);
9618                 }
9619                 mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow;
9620                 mLastWakeLockObscuringWindow = null;
9621                 mHoldingScreenWakeLock.acquire();
9622                 mPolicy.keepScreenOnStartedLw();
9623             } else {
9624                 if (DEBUG_KEEP_SCREEN_ON) {
9625                     Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " +
9626                             mWindowPlacerLocked.mObsuringWindow);
9627                 }
9628                 mLastWakeLockHoldingWindow = null;
9629                 mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow;
9630                 mPolicy.keepScreenOnStoppedLw();
9631                 mHoldingScreenWakeLock.release();
9632             }
9633         }
9634     }
9635
9636     void requestTraversal() {
9637         synchronized (mWindowMap) {
9638             mWindowPlacerLocked.requestTraversal();
9639         }
9640     }
9641
9642     /** Note that Locked in this case is on mLayoutToAnim */
9643     void scheduleAnimationLocked() {
9644         if (!mAnimationScheduled) {
9645             mAnimationScheduled = true;
9646             mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
9647         }
9648     }
9649
9650     boolean needsLayout() {
9651         final int numDisplays = mDisplayContents.size();
9652         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9653             final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9654             if (displayContent.layoutNeeded) {
9655                 return true;
9656             }
9657         }
9658         return false;
9659     }
9660
9661     /** If a window that has an animation specifying a colored background and the current wallpaper
9662      * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9663      * suddenly disappear. */
9664     int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9665         WindowList windows = winAnimator.mWin.getWindowList();
9666         for (int i = windows.size() - 1; i >= 0; --i) {
9667             WindowState testWin = windows.get(i);
9668             if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9669                 return testWin.mWinAnimator.mAnimLayer;
9670             }
9671         }
9672         return winAnimator.mAnimLayer;
9673     }
9674
9675     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9676                                            boolean secure) {
9677         final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
9678         boolean leakedSurface = false;
9679         boolean killedApps = false;
9680
9681         EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9682                 winAnimator.mSession.mPid, operation);
9683
9684         final long callingIdentity = Binder.clearCallingIdentity();
9685         try {
9686             // There was some problem...   first, do a sanity check of the window list to make sure
9687             // we haven't left any dangling surfaces around.
9688
9689             Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
9690             final int numDisplays = mDisplayContents.size();
9691             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9692                 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9693                 final int numWindows = windows.size();
9694                 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9695                     final WindowState ws = windows.get(winNdx);
9696                     final WindowStateAnimator wsa = ws.mWinAnimator;
9697                     if (wsa.mSurfaceController == null) {
9698                         continue;
9699                     }
9700                     if (!mSessions.contains(wsa.mSession)) {
9701                         Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
9702                                 + ws + " surface=" + wsa.mSurfaceController
9703                                 + " token=" + ws.mToken
9704                                 + " pid=" + ws.mSession.mPid
9705                                 + " uid=" + ws.mSession.mUid);
9706                         wsa.destroySurface();
9707                         mForceRemoves.add(ws);
9708                         leakedSurface = true;
9709                     } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9710                         Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
9711                                 + ws + " surface=" + wsa.mSurfaceController
9712                                 + " token=" + ws.mAppToken
9713                                 + " saved=" + ws.hasSavedSurface());
9714                         if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
9715                         wsa.destroySurface();
9716                         leakedSurface = true;
9717                     }
9718                 }
9719             }
9720
9721             if (!leakedSurface) {
9722                 Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!");
9723                 SparseIntArray pidCandidates = new SparseIntArray();
9724                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9725                     final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9726                     final int numWindows = windows.size();
9727                     for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9728                         final WindowState ws = windows.get(winNdx);
9729                         if (mForceRemoves.contains(ws)) {
9730                             continue;
9731                         }
9732                         WindowStateAnimator wsa = ws.mWinAnimator;
9733                         if (wsa.mSurfaceController != null) {
9734                             pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9735                         }
9736                     }
9737                     if (pidCandidates.size() > 0) {
9738                         int[] pids = new int[pidCandidates.size()];
9739                         for (int i=0; i<pids.length; i++) {
9740                             pids[i] = pidCandidates.keyAt(i);
9741                         }
9742                         try {
9743                             if (mActivityManager.killPids(pids, "Free memory", secure)) {
9744                                 killedApps = true;
9745                             }
9746                         } catch (RemoteException e) {
9747                         }
9748                     }
9749                 }
9750             }
9751
9752             if (leakedSurface || killedApps) {
9753                 // We managed to reclaim some memory, so get rid of the trouble
9754                 // surface and ask the app to request another one.
9755                 Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry.");
9756                 if (surfaceController != null) {
9757                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9758                             "RECOVER DESTROY", false);
9759                     winAnimator.destroySurface();
9760                     scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
9761                 }
9762
9763                 try {
9764                     winAnimator.mWin.mClient.dispatchGetNewSurface();
9765                 } catch (RemoteException e) {
9766                 }
9767             }
9768         } finally {
9769             Binder.restoreCallingIdentity(callingIdentity);
9770         }
9771
9772         return leakedSurface || killedApps;
9773     }
9774
9775     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9776         WindowState newFocus = computeFocusedWindowLocked();
9777         if (mCurrentFocus != newFocus) {
9778             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9779             // This check makes sure that we don't already have the focus
9780             // change message pending.
9781             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9782             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9783             // TODO(multidisplay): Focused windows on default display only.
9784             final DisplayContent displayContent = getDefaultDisplayContentLocked();
9785             final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9786                     mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9787                             && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9788             if (imWindowChanged) {
9789                 displayContent.layoutNeeded = true;
9790                 newFocus = computeFocusedWindowLocked();
9791             }
9792
9793             if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
9794                     mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9795             final WindowState oldFocus = mCurrentFocus;
9796             mCurrentFocus = newFocus;
9797             mLosingFocus.remove(newFocus);
9798
9799             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9800
9801             if (imWindowChanged && oldFocus != mInputMethodWindow) {
9802                 // Focus of the input method window changed. Perform layout if needed.
9803                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9804                     mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9805                             updateInputWindows);
9806                     focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9807                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9808                     // Client will do the layout, but we need to assign layers
9809                     // for handleNewWindowLocked() below.
9810                     mLayersController.assignLayersLocked(displayContent.getWindowList());
9811                 }
9812             }
9813
9814             if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9815                 // The change in focus caused us to need to do a layout.  Okay.
9816                 displayContent.layoutNeeded = true;
9817                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9818                     mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9819                             updateInputWindows);
9820                 }
9821             }
9822
9823             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9824                 // If we defer assigning layers, then the caller is responsible for
9825                 // doing this part.
9826                 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9827             }
9828
9829             adjustForImeIfNeeded(displayContent);
9830
9831             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9832             return true;
9833         }
9834         return false;
9835     }
9836
9837     private WindowState computeFocusedWindowLocked() {
9838         final int displayCount = mDisplayContents.size();
9839         for (int i = 0; i < displayCount; i++) {
9840             final DisplayContent displayContent = mDisplayContents.valueAt(i);
9841             WindowState win = findFocusedWindowLocked(displayContent);
9842             if (win != null) {
9843                 return win;
9844             }
9845         }
9846         return null;
9847     }
9848
9849     WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9850         final WindowList windows = displayContent.getWindowList();
9851         for (int i = windows.size() - 1; i >= 0; i--) {
9852             final WindowState win = windows.get(i);
9853
9854             if (localLOGV || DEBUG_FOCUS) Slog.v(
9855                 TAG_WM, "Looking for focus: " + i
9856                 + " = " + win
9857                 + ", flags=" + win.mAttrs.flags
9858                 + ", canReceive=" + win.canReceiveKeys());
9859
9860             if (!win.canReceiveKeys()) {
9861                 continue;
9862             }
9863
9864             AppWindowToken wtoken = win.mAppToken;
9865
9866             // If this window's application has been removed, just skip it.
9867             if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9868                 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
9869                         + (wtoken.removed ? "removed" : "sendingToBottom"));
9870                 continue;
9871             }
9872
9873             // Descend through all of the app tokens and find the first that either matches
9874             // win.mAppToken (return win) or mFocusedApp (return null).
9875             if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9876                     mFocusedApp != null) {
9877                 ArrayList<Task> tasks = displayContent.getTasks();
9878                 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9879                     AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9880                     int tokenNdx = tokens.size() - 1;
9881                     for ( ; tokenNdx >= 0; --tokenNdx) {
9882                         final AppWindowToken token = tokens.get(tokenNdx);
9883                         if (wtoken == token) {
9884                             break;
9885                         }
9886                         if (mFocusedApp == token && token.windowsAreFocusable()) {
9887                             // Whoops, we are below the focused app whose windows are focusable...
9888                             // No focus for you!!!
9889                             if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
9890                                     "findFocusedWindow: Reached focused app=" + mFocusedApp);
9891                             return null;
9892                         }
9893                     }
9894                     if (tokenNdx >= 0) {
9895                         // Early exit from loop, must have found the matching token.
9896                         break;
9897                     }
9898                 }
9899             }
9900
9901             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i +
9902                         " = " + win);
9903             return win;
9904         }
9905
9906         if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
9907         return null;
9908     }
9909
9910     private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9911         if (mDisplayFrozen) {
9912             return;
9913         }
9914
9915         if (!mDisplayReady || !mPolicy.isScreenOn()) {
9916             // No need to freeze the screen before the system is ready or if
9917             // the screen is off.
9918             return;
9919         }
9920
9921         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9922                 "startFreezingDisplayLocked: inTransaction=" + inTransaction
9923                 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
9924                 + " called by " + Debug.getCallers(8));
9925         mScreenFrozenLock.acquire();
9926
9927         mDisplayFrozen = true;
9928         mDisplayFreezeTime = SystemClock.elapsedRealtime();
9929         mLastFinishedFreezeSource = null;
9930
9931         mInputMonitor.freezeInputDispatchingLw();
9932
9933         // Clear the last input window -- that is just used for
9934         // clean transitions between IMEs, and if we are freezing
9935         // the screen then the whole world is changing behind the scenes.
9936         mPolicy.setLastInputMethodWindowLw(null, null);
9937
9938         if (mAppTransition.isTransitionSet()) {
9939             mAppTransition.freeze();
9940         }
9941
9942         if (PROFILE_ORIENTATION) {
9943             File file = new File("/data/system/frozen");
9944             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9945         }
9946
9947         if (CUSTOM_SCREEN_ROTATION) {
9948             mExitAnimId = exitAnim;
9949             mEnterAnimId = enterAnim;
9950             final DisplayContent displayContent = getDefaultDisplayContentLocked();
9951             final int displayId = displayContent.getDisplayId();
9952             ScreenRotationAnimation screenRotationAnimation =
9953                     mAnimator.getScreenRotationAnimationLocked(displayId);
9954             if (screenRotationAnimation != null) {
9955                 screenRotationAnimation.kill();
9956             }
9957
9958             // Check whether the current screen contains any secure content.
9959             boolean isSecure = false;
9960             final WindowList windows = getDefaultWindowListLocked();
9961             final int N = windows.size();
9962             for (int i = 0; i < N; i++) {
9963                 WindowState ws = windows.get(i);
9964                 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
9965                     isSecure = true;
9966                     break;
9967                 }
9968             }
9969
9970             // TODO(multidisplay): rotation on main screen only.
9971             displayContent.updateDisplayInfo();
9972             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9973                     mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
9974             mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9975         }
9976     }
9977
9978     void stopFreezingDisplayLocked() {
9979         if (!mDisplayFrozen) {
9980             return;
9981         }
9982
9983         if (mWaitingForConfig || mAppsFreezingScreen > 0
9984                 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
9985                 || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
9986             if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9987                 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9988                 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9989                 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9990                 + ", mClientFreezingScreen=" + mClientFreezingScreen
9991                 + ", mOpeningApps.size()=" + mOpeningApps.size());
9992             return;
9993         }
9994
9995         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9996                 "stopFreezingDisplayLocked: Unfreezing now");
9997
9998         mDisplayFrozen = false;
9999         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10000         StringBuilder sb = new StringBuilder(128);
10001         sb.append("Screen frozen for ");
10002         TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10003         if (mLastFinishedFreezeSource != null) {
10004             sb.append(" due to ");
10005             sb.append(mLastFinishedFreezeSource);
10006         }
10007         Slog.i(TAG_WM, sb.toString());
10008         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10009         mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10010         if (PROFILE_ORIENTATION) {
10011             Debug.stopMethodTracing();
10012         }
10013
10014         boolean updateRotation = false;
10015
10016         final DisplayContent displayContent = getDefaultDisplayContentLocked();
10017         final int displayId = displayContent.getDisplayId();
10018         ScreenRotationAnimation screenRotationAnimation =
10019                 mAnimator.getScreenRotationAnimationLocked(displayId);
10020         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10021                 && screenRotationAnimation.hasScreenshot()) {
10022             if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
10023             // TODO(multidisplay): rotation on main screen only.
10024             DisplayInfo displayInfo = displayContent.getDisplayInfo();
10025             // Get rotation animation again, with new top window
10026             boolean isDimming = displayContent.isDimming();
10027             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10028                 mExitAnimId = mEnterAnimId = 0;
10029             }
10030             if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10031                     getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
10032                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10033                 scheduleAnimationLocked();
10034             } else {
10035                 screenRotationAnimation.kill();
10036                 mAnimator.setScreenRotationAnimationLocked(displayId, null);
10037                 updateRotation = true;
10038             }
10039         } else {
10040             if (screenRotationAnimation != null) {
10041                 screenRotationAnimation.kill();
10042                 mAnimator.setScreenRotationAnimationLocked(displayId, null);
10043             }
10044             updateRotation = true;
10045         }
10046
10047         mInputMonitor.thawInputDispatchingLw();
10048
10049         boolean configChanged;
10050
10051         // While the display is frozen we don't re-compute the orientation
10052         // to avoid inconsistent states.  However, something interesting
10053         // could have actually changed during that time so re-evaluate it
10054         // now to catch that.
10055         configChanged = updateOrientationFromAppTokensLocked(false);
10056
10057         // A little kludge: a lot could have happened while the
10058         // display was frozen, so now that we are coming back we
10059         // do a gc so that any remote references the system
10060         // processes holds on others can be released if they are
10061         // no longer needed.
10062         mH.removeMessages(H.FORCE_GC);
10063         mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10064
10065         mScreenFrozenLock.release();
10066
10067         if (updateRotation) {
10068             if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
10069             configChanged |= updateRotationUncheckedLocked(false);
10070         }
10071
10072         if (configChanged) {
10073             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10074         }
10075     }
10076
10077     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10078             DisplayMetrics dm) {
10079         if (index < tokens.length) {
10080             String str = tokens[index];
10081             if (str != null && str.length() > 0) {
10082                 try {
10083                     int val = Integer.parseInt(str);
10084                     return val;
10085                 } catch (Exception e) {
10086                 }
10087             }
10088         }
10089         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10090             return defDps;
10091         }
10092         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10093         return val;
10094     }
10095
10096     void createWatermarkInTransaction() {
10097         if (mWatermark != null) {
10098             return;
10099         }
10100
10101         File file = new File("/system/etc/setup.conf");
10102         FileInputStream in = null;
10103         DataInputStream ind = null;
10104         try {
10105             in = new FileInputStream(file);
10106             ind = new DataInputStream(in);
10107             String line = ind.readLine();
10108             if (line != null) {
10109                 String[] toks = line.split("%");
10110                 if (toks != null && toks.length > 0) {
10111                     mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10112                             mRealDisplayMetrics, mFxSession, toks);
10113                 }
10114             }
10115         } catch (FileNotFoundException e) {
10116         } catch (IOException e) {
10117         } finally {
10118             if (ind != null) {
10119                 try {
10120                     ind.close();
10121                 } catch (IOException e) {
10122                 }
10123             } else if (in != null) {
10124                 try {
10125                     in.close();
10126                 } catch (IOException e) {
10127                 }
10128             }
10129         }
10130     }
10131
10132     @Override
10133     public void statusBarVisibilityChanged(int visibility) {
10134         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10135                 != PackageManager.PERMISSION_GRANTED) {
10136             throw new SecurityException("Caller does not hold permission "
10137                     + android.Manifest.permission.STATUS_BAR);
10138         }
10139
10140         synchronized (mWindowMap) {
10141             mLastStatusBarVisibility = visibility;
10142             visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10143             updateStatusBarVisibilityLocked(visibility);
10144         }
10145     }
10146
10147     // TOOD(multidisplay): StatusBar on multiple screens?
10148     boolean updateStatusBarVisibilityLocked(int visibility) {
10149         if (mLastDispatchedSystemUiVisibility == visibility) {
10150             return false;
10151         }
10152         final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
10153                 // We are only interested in differences of one of the
10154                 // clearable flags...
10155                 & View.SYSTEM_UI_CLEARABLE_FLAGS
10156                 // ...if it has actually been cleared.
10157                 & ~visibility;
10158
10159         mLastDispatchedSystemUiVisibility = visibility;
10160         mInputManager.setSystemUiVisibility(visibility);
10161         final WindowList windows = getDefaultWindowListLocked();
10162         final int N = windows.size();
10163         for (int i = 0; i < N; i++) {
10164             WindowState ws = windows.get(i);
10165             try {
10166                 int curValue = ws.mSystemUiVisibility;
10167                 int diff = (curValue ^ visibility) & globalDiff;
10168                 int newValue = (curValue&~diff) | (visibility&diff);
10169                 if (newValue != curValue) {
10170                     ws.mSeq++;
10171                     ws.mSystemUiVisibility = newValue;
10172                 }
10173                 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10174                     ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10175                             visibility, newValue, diff);
10176                 }
10177             } catch (RemoteException e) {
10178                 // so sorry
10179             }
10180         }
10181         return true;
10182     }
10183
10184     @Override
10185     public void reevaluateStatusBarVisibility() {
10186         synchronized (mWindowMap) {
10187             int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10188             if (updateStatusBarVisibilityLocked(visibility)) {
10189                 mWindowPlacerLocked.requestTraversal();
10190             }
10191         }
10192     }
10193
10194     private static final class HideNavInputConsumer extends InputConsumerImpl
10195             implements WindowManagerPolicy.InputConsumer {
10196         private final InputEventReceiver mInputEventReceiver;
10197
10198         HideNavInputConsumer(WindowManagerService service, Looper looper,
10199                              InputEventReceiver.Factory inputEventReceiverFactory) {
10200             super(service, "input consumer", null);
10201             mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
10202                     mClientChannel, looper);
10203         }
10204
10205         @Override
10206         public void dismiss() {
10207             if (mService.removeInputConsumer()) {
10208                 synchronized (mService.mWindowMap) {
10209                     mInputEventReceiver.dispose();
10210                     disposeChannelsLw();
10211                 }
10212             }
10213         }
10214     }
10215
10216     @Override
10217     public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper,
10218             InputEventReceiver.Factory inputEventReceiverFactory) {
10219         synchronized (mWindowMap) {
10220             HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer(
10221                     this, looper, inputEventReceiverFactory);
10222             mInputConsumer = inputConsumerImpl;
10223             mInputMonitor.updateInputWindowsLw(true);
10224             return inputConsumerImpl;
10225         }
10226     }
10227
10228     boolean removeInputConsumer() {
10229         synchronized (mWindowMap) {
10230             if (mInputConsumer != null) {
10231                 mInputConsumer = null;
10232                 mInputMonitor.updateInputWindowsLw(true);
10233                 return true;
10234             }
10235             return false;
10236         }
10237     }
10238
10239     @Override
10240     public void createWallpaperInputConsumer(InputChannel inputChannel) {
10241         synchronized (mWindowMap) {
10242             mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel);
10243             mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true;
10244             mInputMonitor.updateInputWindowsLw(true);
10245         }
10246     }
10247
10248     @Override
10249     public void removeWallpaperInputConsumer() {
10250         synchronized (mWindowMap) {
10251             if (mWallpaperInputConsumer != null) {
10252                 mWallpaperInputConsumer.disposeChannelsLw();
10253                 mWallpaperInputConsumer = null;
10254                 mInputMonitor.updateInputWindowsLw(true);
10255             }
10256         }
10257     }
10258
10259     @Override
10260     public boolean hasNavigationBar() {
10261         return mPolicy.hasNavigationBar();
10262     }
10263
10264     @Override
10265     public void lockNow(Bundle options) {
10266         mPolicy.lockNow(options);
10267     }
10268
10269     public void showRecentApps(boolean fromHome) {
10270         mPolicy.showRecentApps(fromHome);
10271     }
10272
10273     @Override
10274     public boolean isSafeModeEnabled() {
10275         return mSafeMode;
10276     }
10277
10278     @Override
10279     public boolean clearWindowContentFrameStats(IBinder token) {
10280         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10281                 "clearWindowContentFrameStats()")) {
10282             throw new SecurityException("Requires FRAME_STATS permission");
10283         }
10284         synchronized (mWindowMap) {
10285             WindowState windowState = mWindowMap.get(token);
10286             if (windowState == null) {
10287                 return false;
10288             }
10289             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
10290             if (surfaceController == null) {
10291                 return false;
10292             }
10293             return surfaceController.clearWindowContentFrameStats();
10294         }
10295     }
10296
10297     @Override
10298     public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10299         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10300                 "getWindowContentFrameStats()")) {
10301             throw new SecurityException("Requires FRAME_STATS permission");
10302         }
10303         synchronized (mWindowMap) {
10304             WindowState windowState = mWindowMap.get(token);
10305             if (windowState == null) {
10306                 return null;
10307             }
10308             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
10309             if (surfaceController == null) {
10310                 return null;
10311             }
10312             if (mTempWindowRenderStats == null) {
10313                 mTempWindowRenderStats = new WindowContentFrameStats();
10314             }
10315             WindowContentFrameStats stats = mTempWindowRenderStats;
10316             if (!surfaceController.getWindowContentFrameStats(stats)) {
10317                 return null;
10318             }
10319             return stats;
10320         }
10321     }
10322
10323     public void notifyAppRelaunching(IBinder token) {
10324         synchronized (mWindowMap) {
10325             AppWindowToken appWindow = findAppWindowToken(token);
10326             if (appWindow != null) {
10327                 appWindow.startRelaunching();
10328             }
10329         }
10330     }
10331
10332     public void notifyAppRelaunchingFinished(IBinder token) {
10333         synchronized (mWindowMap) {
10334             AppWindowToken appWindow = findAppWindowToken(token);
10335             if (appWindow != null) {
10336                 appWindow.finishRelaunching();
10337             }
10338         }
10339     }
10340
10341     public void notifyAppRelaunchesCleared(IBinder token) {
10342         synchronized (mWindowMap) {
10343             final AppWindowToken appWindow = findAppWindowToken(token);
10344             if (appWindow != null) {
10345                 appWindow.clearRelaunching();
10346             }
10347         }
10348     }
10349
10350     @Override
10351     public int getDockedDividerInsetsLw() {
10352         return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
10353     }
10354
10355     void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10356         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10357         mPolicy.dump("    ", pw, args);
10358     }
10359
10360     void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10361         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10362         mAnimator.dumpLocked(pw, "    ", dumpAll);
10363     }
10364
10365     void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10366         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10367         if (!mTokenMap.isEmpty()) {
10368             pw.println("  All tokens:");
10369             Iterator<WindowToken> it = mTokenMap.values().iterator();
10370             while (it.hasNext()) {
10371                 WindowToken token = it.next();
10372                 pw.print("  "); pw.print(token);
10373                 if (dumpAll) {
10374                     pw.println(':');
10375                     token.dump(pw, "    ");
10376                 } else {
10377                     pw.println();
10378                 }
10379             }
10380         }
10381         mWallpaperControllerLocked.dumpTokens(pw, "  ", dumpAll);
10382         if (!mFinishedStarting.isEmpty()) {
10383             pw.println();
10384             pw.println("  Finishing start of application tokens:");
10385             for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10386                 WindowToken token = mFinishedStarting.get(i);
10387                 pw.print("  Finished Starting #"); pw.print(i);
10388                         pw.print(' '); pw.print(token);
10389                 if (dumpAll) {
10390                     pw.println(':');
10391                     token.dump(pw, "    ");
10392                 } else {
10393                     pw.println();
10394                 }
10395             }
10396         }
10397         if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
10398             pw.println();
10399             if (mOpeningApps.size() > 0) {
10400                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10401             }
10402             if (mClosingApps.size() > 0) {
10403                 pw.print("  mClosingApps="); pw.println(mClosingApps);
10404             }
10405         }
10406     }
10407
10408     void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10409         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10410         for (int i=0; i<mSessions.size(); i++) {
10411             Session s = mSessions.valueAt(i);
10412             pw.print("  Session "); pw.print(s); pw.println(':');
10413             s.dump(pw, "    ");
10414         }
10415     }
10416
10417     void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10418         pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10419         if (mDisplayReady) {
10420             final int numDisplays = mDisplayContents.size();
10421             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10422                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10423                 displayContent.dump("  ", pw);
10424             }
10425         } else {
10426             pw.println("  NO DISPLAY");
10427         }
10428     }
10429
10430     void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10431             ArrayList<WindowState> windows) {
10432         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10433         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10434     }
10435
10436     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10437             ArrayList<WindowState> windows) {
10438         final int numDisplays = mDisplayContents.size();
10439         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10440             final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10441             for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10442                 final WindowState w = windowList.get(winNdx);
10443                 if (windows == null || windows.contains(w)) {
10444                     pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10445                             pw.print(w); pw.println(":");
10446                     w.dump(pw, "    ", dumpAll || windows != null);
10447                 }
10448             }
10449         }
10450         if (mInputMethodDialogs.size() > 0) {
10451             pw.println();
10452             pw.println("  Input method dialogs:");
10453             for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10454                 WindowState w = mInputMethodDialogs.get(i);
10455                 if (windows == null || windows.contains(w)) {
10456                     pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10457                 }
10458             }
10459         }
10460         if (mPendingRemove.size() > 0) {
10461             pw.println();
10462             pw.println("  Remove pending for:");
10463             for (int i=mPendingRemove.size()-1; i>=0; i--) {
10464                 WindowState w = mPendingRemove.get(i);
10465                 if (windows == null || windows.contains(w)) {
10466                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
10467                             pw.print(w);
10468                     if (dumpAll) {
10469                         pw.println(":");
10470                         w.dump(pw, "    ", true);
10471                     } else {
10472                         pw.println();
10473                     }
10474                 }
10475             }
10476         }
10477         if (mForceRemoves != null && mForceRemoves.size() > 0) {
10478             pw.println();
10479             pw.println("  Windows force removing:");
10480             for (int i=mForceRemoves.size()-1; i>=0; i--) {
10481                 WindowState w = mForceRemoves.get(i);
10482                 pw.print("  Removing #"); pw.print(i); pw.print(' ');
10483                         pw.print(w);
10484                 if (dumpAll) {
10485                     pw.println(":");
10486                     w.dump(pw, "    ", true);
10487                 } else {
10488                     pw.println();
10489                 }
10490             }
10491         }
10492         if (mDestroySurface.size() > 0) {
10493             pw.println();
10494             pw.println("  Windows waiting to destroy their surface:");
10495             for (int i=mDestroySurface.size()-1; i>=0; i--) {
10496                 WindowState w = mDestroySurface.get(i);
10497                 if (windows == null || windows.contains(w)) {
10498                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10499                             pw.print(w);
10500                     if (dumpAll) {
10501                         pw.println(":");
10502                         w.dump(pw, "    ", true);
10503                     } else {
10504                         pw.println();
10505                     }
10506                 }
10507             }
10508         }
10509         if (mLosingFocus.size() > 0) {
10510             pw.println();
10511             pw.println("  Windows losing focus:");
10512             for (int i=mLosingFocus.size()-1; i>=0; i--) {
10513                 WindowState w = mLosingFocus.get(i);
10514                 if (windows == null || windows.contains(w)) {
10515                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
10516                             pw.print(w);
10517                     if (dumpAll) {
10518                         pw.println(":");
10519                         w.dump(pw, "    ", true);
10520                     } else {
10521                         pw.println();
10522                     }
10523                 }
10524             }
10525         }
10526         if (mResizingWindows.size() > 0) {
10527             pw.println();
10528             pw.println("  Windows waiting to resize:");
10529             for (int i=mResizingWindows.size()-1; i>=0; i--) {
10530                 WindowState w = mResizingWindows.get(i);
10531                 if (windows == null || windows.contains(w)) {
10532                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10533                             pw.print(w);
10534                     if (dumpAll) {
10535                         pw.println(":");
10536                         w.dump(pw, "    ", true);
10537                     } else {
10538                         pw.println();
10539                     }
10540                 }
10541             }
10542         }
10543         if (mWaitingForDrawn.size() > 0) {
10544             pw.println();
10545             pw.println("  Clients waiting for these windows to be drawn:");
10546             for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10547                 WindowState win = mWaitingForDrawn.get(i);
10548                 pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10549             }
10550         }
10551         pw.println();
10552         pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10553         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
10554         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10555         if (mLastFocus != mCurrentFocus) {
10556             pw.print("  mLastFocus="); pw.println(mLastFocus);
10557         }
10558         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10559         if (mInputMethodTarget != null) {
10560             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10561         }
10562         pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10563                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10564         pw.print("  mLastDisplayFreezeDuration=");
10565                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10566                 if ( mLastFinishedFreezeSource != null) {
10567                     pw.print(" due to ");
10568                     pw.print(mLastFinishedFreezeSource);
10569                 }
10570                 pw.println();
10571         pw.print("  mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
10572                 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
10573                 pw.println();
10574
10575         mInputMonitor.dump(pw, "  ");
10576
10577         if (dumpAll) {
10578             pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10579                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10580             if (mLastStatusBarVisibility != 0) {
10581                 pw.print("  mLastStatusBarVisibility=0x");
10582                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
10583             }
10584             if (mInputMethodWindow != null) {
10585                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10586             }
10587             mWindowPlacerLocked.dump(pw, "  ");
10588             mWallpaperControllerLocked.dump(pw, "  ");
10589             mLayersController.dump(pw, "  ");
10590             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10591                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10592             if (needsLayout()) {
10593                 pw.print("  layoutNeeded on displays=");
10594                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10595                     final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10596                     if (displayContent.layoutNeeded) {
10597                         pw.print(displayContent.getDisplayId());
10598                     }
10599                 }
10600                 pw.println();
10601             }
10602             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10603             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10604                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10605                     pw.print(" client="); pw.print(mClientFreezingScreen);
10606                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
10607                     pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10608             pw.print("  mRotation="); pw.print(mRotation);
10609                     pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10610             pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10611                     pw.print(" mLastOrientation="); pw.println(mLastOrientation);
10612             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10613             pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
10614                     pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10615                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10616                     pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10617             pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
10618             pw.println("  mLayoutToAnim:");
10619             mAppTransition.dump(pw, "    ");
10620         }
10621     }
10622
10623     boolean dumpWindows(PrintWriter pw, String name, String[] args,
10624             int opti, boolean dumpAll) {
10625         WindowList windows = new WindowList();
10626         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
10627             final boolean appsOnly = name.contains("apps");
10628             final boolean visibleOnly = name.contains("visible");
10629             synchronized(mWindowMap) {
10630                 if (appsOnly) {
10631                     dumpDisplayContentsLocked(pw, true);
10632                 }
10633
10634                 final int numDisplays = mDisplayContents.size();
10635                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10636                     final WindowList windowList =
10637                             mDisplayContents.valueAt(displayNdx).getWindowList();
10638                     for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10639                         final WindowState w = windowList.get(winNdx);
10640                         if ((!visibleOnly || w.mWinAnimator.getShown())
10641                                 && (!appsOnly || w.mAppToken != null)) {
10642                             windows.add(w);
10643                         }
10644                     }
10645                 }
10646             }
10647         } else {
10648             int objectId = 0;
10649             // See if this is an object ID.
10650             try {
10651                 objectId = Integer.parseInt(name, 16);
10652                 name = null;
10653             } catch (RuntimeException e) {
10654             }
10655             synchronized(mWindowMap) {
10656                 final int numDisplays = mDisplayContents.size();
10657                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10658                     final WindowList windowList =
10659                             mDisplayContents.valueAt(displayNdx).getWindowList();
10660                     for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10661                         final WindowState w = windowList.get(winNdx);
10662                         if (name != null) {
10663                             if (w.mAttrs.getTitle().toString().contains(name)) {
10664                                 windows.add(w);
10665                             }
10666                         } else if (System.identityHashCode(w) == objectId) {
10667                             windows.add(w);
10668                         }
10669                     }
10670                 }
10671             }
10672         }
10673
10674         if (windows.size() <= 0) {
10675             return false;
10676         }
10677
10678         synchronized(mWindowMap) {
10679             dumpWindowsLocked(pw, dumpAll, windows);
10680         }
10681         return true;
10682     }
10683
10684     void dumpLastANRLocked(PrintWriter pw) {
10685         pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10686         if (mLastANRState == null) {
10687             pw.println("  <no ANR has occurred since boot>");
10688         } else {
10689             pw.println(mLastANRState);
10690         }
10691     }
10692
10693     /**
10694      * Saves information about the state of the window manager at
10695      * the time an ANR occurred before anything else in the system changes
10696      * in response.
10697      *
10698      * @param appWindowToken The application that ANR'd, may be null.
10699      * @param windowState The window that ANR'd, may be null.
10700      * @param reason The reason for the ANR, may be null.
10701      */
10702     public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10703             String reason) {
10704         StringWriter sw = new StringWriter();
10705         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10706         pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10707         if (appWindowToken != null) {
10708             pw.println("  Application at fault: " + appWindowToken.stringName);
10709         }
10710         if (windowState != null) {
10711             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10712         }
10713         if (reason != null) {
10714             pw.println("  Reason: " + reason);
10715         }
10716         pw.println();
10717         dumpWindowsNoHeaderLocked(pw, true, null);
10718         pw.println();
10719         pw.println("Last ANR continued");
10720         dumpDisplayContentsLocked(pw, true);
10721         pw.close();
10722         mLastANRState = sw.toString();
10723
10724         mH.removeMessages(H.RESET_ANR_MESSAGE);
10725         mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
10726     }
10727
10728     @Override
10729     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10730         if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10731                 != PackageManager.PERMISSION_GRANTED) {
10732             pw.println("Permission Denial: can't dump WindowManager from from pid="
10733                     + Binder.getCallingPid()
10734                     + ", uid=" + Binder.getCallingUid());
10735             return;
10736         }
10737
10738         boolean dumpAll = false;
10739
10740         int opti = 0;
10741         while (opti < args.length) {
10742             String opt = args[opti];
10743             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10744                 break;
10745             }
10746             opti++;
10747             if ("-a".equals(opt)) {
10748                 dumpAll = true;
10749             } else if ("-h".equals(opt)) {
10750                 pw.println("Window manager dump options:");
10751                 pw.println("  [-a] [-h] [cmd] ...");
10752                 pw.println("  cmd may be one of:");
10753                 pw.println("    l[astanr]: last ANR information");
10754                 pw.println("    p[policy]: policy state");
10755                 pw.println("    a[animator]: animator state");
10756                 pw.println("    s[essions]: active sessions");
10757                 pw.println("    surfaces: active surfaces (debugging enabled only)");
10758                 pw.println("    d[isplays]: active display contents");
10759                 pw.println("    t[okens]: token list");
10760                 pw.println("    w[indows]: window list");
10761                 pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10762                 pw.println("    be a partial substring in a window name, a");
10763                 pw.println("    Window hex object identifier, or");
10764                 pw.println("    \"all\" for all windows, or");
10765                 pw.println("    \"visible\" for the visible windows.");
10766                 pw.println("    \"visible-apps\" for the visible app windows.");
10767                 pw.println("  -a: include all available server state.");
10768                 return;
10769             } else {
10770                 pw.println("Unknown argument: " + opt + "; use -h for help");
10771             }
10772         }
10773
10774         // Is the caller requesting to dump a particular piece of data?
10775         if (opti < args.length) {
10776             String cmd = args[opti];
10777             opti++;
10778             if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10779                 synchronized(mWindowMap) {
10780                     dumpLastANRLocked(pw);
10781                 }
10782                 return;
10783             } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10784                 synchronized(mWindowMap) {
10785                     dumpPolicyLocked(pw, args, true);
10786                 }
10787                 return;
10788             } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10789                 synchronized(mWindowMap) {
10790                     dumpAnimatorLocked(pw, args, true);
10791                 }
10792                 return;
10793             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10794                 synchronized(mWindowMap) {
10795                     dumpSessionsLocked(pw, true);
10796                 }
10797                 return;
10798             } else if ("surfaces".equals(cmd)) {
10799                 synchronized(mWindowMap) {
10800                     WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
10801                 }
10802                 return;
10803             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10804                 synchronized(mWindowMap) {
10805                     dumpDisplayContentsLocked(pw, true);
10806                 }
10807                 return;
10808             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10809                 synchronized(mWindowMap) {
10810                     dumpTokensLocked(pw, true);
10811                 }
10812                 return;
10813             } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10814                 synchronized(mWindowMap) {
10815                     dumpWindowsLocked(pw, true, null);
10816                 }
10817                 return;
10818             } else if ("all".equals(cmd) || "a".equals(cmd)) {
10819                 synchronized(mWindowMap) {
10820                     dumpWindowsLocked(pw, true, null);
10821                 }
10822                 return;
10823             } else {
10824                 // Dumping a single name?
10825                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10826                     pw.println("Bad window command, or no windows match: " + cmd);
10827                     pw.println("Use -h for help.");
10828                 }
10829                 return;
10830             }
10831         }
10832
10833         synchronized(mWindowMap) {
10834             pw.println();
10835             if (dumpAll) {
10836                 pw.println("-------------------------------------------------------------------------------");
10837             }
10838             dumpLastANRLocked(pw);
10839             pw.println();
10840             if (dumpAll) {
10841                 pw.println("-------------------------------------------------------------------------------");
10842             }
10843             dumpPolicyLocked(pw, args, dumpAll);
10844             pw.println();
10845             if (dumpAll) {
10846                 pw.println("-------------------------------------------------------------------------------");
10847             }
10848             dumpAnimatorLocked(pw, args, dumpAll);
10849             pw.println();
10850             if (dumpAll) {
10851                 pw.println("-------------------------------------------------------------------------------");
10852             }
10853             dumpSessionsLocked(pw, dumpAll);
10854             pw.println();
10855             if (dumpAll) {
10856                 pw.println("-------------------------------------------------------------------------------");
10857             }
10858             WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
10859                     "-------------------------------------------------------------------------------"
10860                     : null);
10861             pw.println();
10862             if (dumpAll) {
10863                 pw.println("-------------------------------------------------------------------------------");
10864             }
10865             dumpDisplayContentsLocked(pw, dumpAll);
10866             pw.println();
10867             if (dumpAll) {
10868                 pw.println("-------------------------------------------------------------------------------");
10869             }
10870             dumpTokensLocked(pw, dumpAll);
10871             pw.println();
10872             if (dumpAll) {
10873                 pw.println("-------------------------------------------------------------------------------");
10874             }
10875             dumpWindowsLocked(pw, dumpAll, null);
10876         }
10877     }
10878
10879     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10880     @Override
10881     public void monitor() {
10882         synchronized (mWindowMap) { }
10883     }
10884
10885     private DisplayContent newDisplayContentLocked(final Display display) {
10886         DisplayContent displayContent = new DisplayContent(display, this);
10887         final int displayId = display.getDisplayId();
10888         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
10889         mDisplayContents.put(displayId, displayContent);
10890
10891         DisplayInfo displayInfo = displayContent.getDisplayInfo();
10892         final Rect rect = new Rect();
10893         mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
10894         displayInfo.overscanLeft = rect.left;
10895         displayInfo.overscanTop = rect.top;
10896         displayInfo.overscanRight = rect.right;
10897         displayInfo.overscanBottom = rect.bottom;
10898         mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo);
10899         configureDisplayPolicyLocked(displayContent);
10900
10901         // TODO: Create an input channel for each display with touch capability.
10902         if (displayId == Display.DEFAULT_DISPLAY) {
10903             displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
10904             registerPointerEventListener(displayContent.mTapDetector);
10905             registerPointerEventListener(mMousePositionTracker);
10906         }
10907
10908         return displayContent;
10909     }
10910
10911     public void createDisplayContentLocked(final Display display) {
10912         if (display == null) {
10913             throw new IllegalArgumentException("getDisplayContent: display must not be null");
10914         }
10915         getDisplayContentLocked(display.getDisplayId());
10916     }
10917
10918     /**
10919      * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10920      * there is a Display for the displayId.
10921      * @param displayId The display the caller is interested in.
10922      * @return The DisplayContent associated with displayId or null if there is no Display for it.
10923      */
10924     public DisplayContent getDisplayContentLocked(final int displayId) {
10925         DisplayContent displayContent = mDisplayContents.get(displayId);
10926         if (displayContent == null) {
10927             final Display display = mDisplayManager.getDisplay(displayId);
10928             if (display != null) {
10929                 displayContent = newDisplayContentLocked(display);
10930             }
10931         }
10932         return displayContent;
10933     }
10934
10935     // There is an inherent assumption that this will never return null.
10936     public DisplayContent getDefaultDisplayContentLocked() {
10937         return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10938     }
10939
10940     public WindowList getDefaultWindowListLocked() {
10941         return getDefaultDisplayContentLocked().getWindowList();
10942     }
10943
10944     public DisplayInfo getDefaultDisplayInfoLocked() {
10945         return getDefaultDisplayContentLocked().getDisplayInfo();
10946     }
10947
10948     /**
10949      * Return the list of WindowStates associated on the passed display.
10950      * @param display The screen to return windows from.
10951      * @return The list of WindowStates on the screen, or null if the there is no screen.
10952      */
10953     public WindowList getWindowListLocked(final Display display) {
10954         return getWindowListLocked(display.getDisplayId());
10955     }
10956
10957     /**
10958      * Return the list of WindowStates associated on the passed display.
10959      * @param displayId The screen to return windows from.
10960      * @return The list of WindowStates on the screen, or null if the there is no screen.
10961      */
10962     public WindowList getWindowListLocked(final int displayId) {
10963         final DisplayContent displayContent = getDisplayContentLocked(displayId);
10964         return displayContent != null ? displayContent.getWindowList() : null;
10965     }
10966
10967     public void onDisplayAdded(int displayId) {
10968         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10969     }
10970
10971     public void handleDisplayAdded(int displayId) {
10972         synchronized (mWindowMap) {
10973             final Display display = mDisplayManager.getDisplay(displayId);
10974             if (display != null) {
10975                 createDisplayContentLocked(display);
10976                 displayReady(displayId);
10977             }
10978             mWindowPlacerLocked.requestTraversal();
10979         }
10980     }
10981
10982     public void onDisplayRemoved(int displayId) {
10983         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10984     }
10985
10986     private void handleDisplayRemovedLocked(int displayId) {
10987         final DisplayContent displayContent = getDisplayContentLocked(displayId);
10988         if (displayContent != null) {
10989             if (displayContent.isAnimating()) {
10990                 displayContent.mDeferredRemoval = true;
10991                 return;
10992             }
10993             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent);
10994             mDisplayContents.delete(displayId);
10995             displayContent.close();
10996             if (displayId == Display.DEFAULT_DISPLAY) {
10997                 unregisterPointerEventListener(displayContent.mTapDetector);
10998                 unregisterPointerEventListener(mMousePositionTracker);
10999             }
11000         }
11001         mAnimator.removeDisplayLocked(displayId);
11002         mWindowPlacerLocked.requestTraversal();
11003     }
11004
11005     public void onDisplayChanged(int displayId) {
11006         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11007     }
11008
11009     private void handleDisplayChangedLocked(int displayId) {
11010         final DisplayContent displayContent = getDisplayContentLocked(displayId);
11011         if (displayContent != null) {
11012             displayContent.updateDisplayInfo();
11013         }
11014         mWindowPlacerLocked.requestTraversal();
11015     }
11016
11017     @Override
11018     public Object getWindowManagerLock() {
11019         return mWindowMap;
11020     }
11021
11022     /**
11023      * Hint to a token that its activity will relaunch, which will trigger removal and addition of
11024      * a window.
11025      * @param token Application token for which the activity will be relaunched.
11026      */
11027     public void setReplacingWindow(IBinder token, boolean animate) {
11028         AppWindowToken appWindowToken = null;
11029         synchronized (mWindowMap) {
11030             appWindowToken = findAppWindowToken(token);
11031             if (appWindowToken == null || !appWindowToken.isVisible()) {
11032                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
11033                         + token);
11034                 return;
11035             }
11036             appWindowToken.setReplacingWindows(animate);
11037         }
11038     }
11039
11040     /**
11041      * Hint to a token that its windows will be replaced across activity relaunch.
11042      * The windows would otherwise be removed  shortly following this as the
11043      * activity is torn down.
11044      * @param token Application token for which the activity will be relaunched.
11045      * @param childrenOnly Whether to mark only child windows for replacement
11046      *                     (for the case where main windows are being preserved/
11047      *                     reused rather than replaced).
11048      *
11049      */
11050     public void setReplacingWindows(IBinder token, boolean childrenOnly) {
11051         AppWindowToken appWindowToken = null;
11052         synchronized (mWindowMap) {
11053             appWindowToken = findAppWindowToken(token);
11054             if (appWindowToken == null || !appWindowToken.isVisible()) {
11055                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
11056                         + token);
11057                 return;
11058             }
11059
11060             if (childrenOnly) {
11061                 appWindowToken.setReplacingChildren();
11062             } else {
11063                 appWindowToken.setReplacingWindows(false /* animate */);
11064             }
11065
11066             scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
11067         }
11068     }
11069
11070     /**
11071      * If we're replacing the window, schedule a timer to clear the replaced window
11072      * after a timeout, in case the replacing window is not coming.
11073      *
11074      * If we're not replacing the window, clear the replace window settings of the app.
11075      *
11076      * @param token Application token for the activity whose window might be replaced.
11077      * @param replacing Whether the window is being replaced or not.
11078      */
11079     public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) {
11080         AppWindowToken appWindowToken = null;
11081         synchronized (mWindowMap) {
11082             appWindowToken = findAppWindowToken(token);
11083             if (appWindowToken == null) {
11084                 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
11085                         + token);
11086                 return;
11087             }
11088             if (replacing) {
11089                 scheduleReplacingWindowTimeouts(appWindowToken);
11090             } else {
11091                 appWindowToken.resetReplacingWindows();
11092             }
11093         }
11094     }
11095
11096     void scheduleReplacingWindowTimeouts(AppWindowToken appWindowToken) {
11097         if (!mReplacingWindowTimeouts.contains(appWindowToken)) {
11098             mReplacingWindowTimeouts.add(appWindowToken);
11099         }
11100         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
11101         mH.sendEmptyMessageDelayed(
11102                 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
11103     }
11104
11105     @Override
11106     public int getDockedStackSide() {
11107         synchronized (mWindowMap) {
11108             final TaskStack dockedStack = getDefaultDisplayContentLocked()
11109                     .getDockedStackVisibleForUserLocked();
11110             return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
11111         }
11112     }
11113
11114     @Override
11115     public void setDockedStackResizing(boolean resizing) {
11116         synchronized (mWindowMap) {
11117             getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
11118             requestTraversal();
11119         }
11120     }
11121
11122     @Override
11123     public void setDockedStackDividerTouchRegion(Rect touchRegion) {
11124         synchronized (mWindowMap) {
11125             getDefaultDisplayContentLocked().getDockedDividerController()
11126                     .setTouchRegion(touchRegion);
11127             setFocusTaskRegionLocked();
11128         }
11129     }
11130
11131     @Override
11132     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
11133         synchronized (mWindowMap) {
11134             getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
11135                     visible, targetStackId, alpha);
11136         }
11137     }
11138
11139     public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
11140         synchronized (mWindowMap) {
11141             final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
11142             if (stack == null) {
11143                 Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
11144                 return;
11145             }
11146             final Rect originalBounds = new Rect();
11147             stack.getBounds(originalBounds);
11148             UiThread.getHandler().post(new Runnable() {
11149                 @Override
11150                 public void run() {
11151                     mBoundsAnimationController.animateBounds(
11152                             stack, originalBounds, bounds, animationDuration);
11153                 }
11154             });
11155         }
11156     }
11157
11158     public void setTaskResizeable(int taskId, int resizeMode) {
11159         synchronized (mWindowMap) {
11160             final Task task = mTaskIdToTask.get(taskId);
11161             if (task != null) {
11162                 task.setResizeable(resizeMode);
11163             }
11164         }
11165     }
11166
11167     public void setForceResizableTasks(boolean forceResizableTasks) {
11168         synchronized (mWindowMap) {
11169             mForceResizableTasks = forceResizableTasks;
11170         }
11171     }
11172
11173     static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
11174         return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
11175     }
11176
11177     @Override
11178     public void registerDockedStackListener(IDockedStackListener listener) {
11179         if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
11180                 "registerDockedStackListener()")) {
11181             return;
11182         }
11183         // TODO(multi-display): The listener is registered on the default display only.
11184         getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
11185                 listener);
11186     }
11187
11188     @Override
11189     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
11190         try {
11191             WindowState focusedWindow = getFocusedWindow();
11192             if (focusedWindow != null && focusedWindow.mClient != null) {
11193                 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
11194             }
11195         } catch (RemoteException e) {
11196         }
11197     }
11198
11199     @Override
11200     public void getStableInsets(Rect outInsets) throws RemoteException {
11201         synchronized (mWindowMap) {
11202             getStableInsetsLocked(outInsets);
11203         }
11204     }
11205
11206     void getStableInsetsLocked(Rect outInsets) {
11207         final DisplayInfo di = getDefaultDisplayInfoLocked();
11208         mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
11209     }
11210
11211     private void getNonDecorInsetsLocked(Rect outInsets) {
11212         final DisplayInfo di = getDefaultDisplayInfoLocked();
11213         mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
11214     }
11215
11216     /**
11217      * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
11218      * inset areas.
11219      *
11220      * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
11221      */
11222     public void subtractStableInsets(Rect inOutBounds) {
11223         synchronized (mWindowMap) {
11224             getStableInsetsLocked(mTmpRect2);
11225             final DisplayInfo di = getDefaultDisplayInfoLocked();
11226             mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
11227             subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
11228         }
11229     }
11230
11231     /**
11232      * Intersects the specified {@code inOutBounds} with the display frame that excludes
11233      * areas that could never be removed in Honeycomb. See
11234      * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
11235      *
11236      * @param inOutBounds The inOutBounds to subtract the inset areas from.
11237      */
11238     public void subtractNonDecorInsets(Rect inOutBounds) {
11239         synchronized (mWindowMap) {
11240             getNonDecorInsetsLocked(mTmpRect2);
11241             final DisplayInfo di = getDefaultDisplayInfoLocked();
11242             mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
11243             subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
11244         }
11245     }
11246
11247     void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
11248         mTmpRect3.set(display);
11249         mTmpRect3.inset(insets);
11250         inOutBounds.intersect(mTmpRect3);
11251     }
11252
11253     /**
11254      * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
11255      * across all screen orientations, and returns the minimum of the task width taking into account
11256      * that the bounds might change because the snap algorithm snaps to a different value.
11257      *
11258      * @return the smallest width to be used in the Configuration, in dips
11259      */
11260     public int getSmallestWidthForTaskBounds(Rect bounds) {
11261         synchronized (mWindowMap) {
11262             return getDefaultDisplayContentLocked().getDockedDividerController()
11263                     .getSmallestWidthDpForBounds(bounds);
11264         }
11265     }
11266
11267     private MousePositionTracker mMousePositionTracker = new MousePositionTracker();
11268
11269     private static class MousePositionTracker implements PointerEventListener {
11270         private boolean mLatestEventWasMouse;
11271         private float mLatestMouseX;
11272         private float mLatestMouseY;
11273
11274         void updatePosition(float x, float y) {
11275             synchronized (this) {
11276                 mLatestEventWasMouse = true;
11277                 mLatestMouseX = x;
11278                 mLatestMouseY = y;
11279             }
11280         }
11281
11282         @Override
11283         public void onPointerEvent(MotionEvent motionEvent) {
11284             if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
11285                 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
11286             } else {
11287                 synchronized (this) {
11288                     mLatestEventWasMouse = false;
11289                 }
11290             }
11291         }
11292     };
11293
11294     void updatePointerIcon(IWindow client) {
11295         float mouseX, mouseY;
11296
11297         synchronized(mMousePositionTracker) {
11298             if (!mMousePositionTracker.mLatestEventWasMouse) {
11299                 return;
11300             }
11301             mouseX = mMousePositionTracker.mLatestMouseX;
11302             mouseY = mMousePositionTracker.mLatestMouseY;
11303         }
11304
11305         synchronized (mWindowMap) {
11306             if (mDragState != null) {
11307                 // Drag cursor overrides the app cursor.
11308                 return;
11309             }
11310             WindowState callingWin = windowForClientLocked(null, client, false);
11311             if (callingWin == null) {
11312                 Slog.w(TAG_WM, "Bad requesting window " + client);
11313                 return;
11314             }
11315             final DisplayContent displayContent = callingWin.getDisplayContent();
11316             if (displayContent == null) {
11317                 return;
11318             }
11319             WindowState windowUnderPointer =
11320                     displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
11321             if (windowUnderPointer != callingWin) {
11322                 return;
11323             }
11324             try {
11325                 windowUnderPointer.mClient.updatePointerIcon(
11326                         windowUnderPointer.translateToWindowX(mouseX),
11327                         windowUnderPointer.translateToWindowY(mouseY));
11328             } catch (RemoteException e) {
11329                 Slog.w(TAG_WM, "unable to update pointer icon");
11330             }
11331         }
11332     }
11333
11334     void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
11335         // Mouse position tracker has not been getting updates while dragging, update it now.
11336         mMousePositionTracker.updatePosition(latestX, latestY);
11337
11338         WindowState windowUnderPointer =
11339                 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
11340         if (windowUnderPointer != null) {
11341             try {
11342                 windowUnderPointer.mClient.updatePointerIcon(
11343                         windowUnderPointer.translateToWindowX(latestX),
11344                         windowUnderPointer.translateToWindowY(latestY));
11345             } catch (RemoteException e) {
11346                 Slog.w(TAG_WM, "unable to restore pointer icon");
11347             }
11348         } else {
11349             InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
11350         }
11351     }
11352
11353     @Override
11354     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
11355             throws RemoteException {
11356         if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
11357                 "registerShortcutKey")) {
11358             throw new SecurityException(
11359                     "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
11360         }
11361         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
11362     }
11363
11364     private final class LocalService extends WindowManagerInternal {
11365         @Override
11366         public void requestTraversalFromDisplayManager() {
11367             requestTraversal();
11368         }
11369
11370         @Override
11371         public void setMagnificationSpec(MagnificationSpec spec) {
11372             synchronized (mWindowMap) {
11373                 if (mAccessibilityController != null) {
11374                     mAccessibilityController.setMagnificationSpecLocked(spec);
11375                 } else {
11376                     throw new IllegalStateException("Magnification callbacks not set!");
11377                 }
11378             }
11379             if (Binder.getCallingPid() != android.os.Process.myPid()) {
11380                 spec.recycle();
11381             }
11382         }
11383
11384         @Override
11385         public void getMagnificationRegion(@NonNull Region magnificationRegion) {
11386             synchronized (mWindowMap) {
11387                 if (mAccessibilityController != null) {
11388                     mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
11389                 } else {
11390                     throw new IllegalStateException("Magnification callbacks not set!");
11391                 }
11392             }
11393         }
11394
11395         @Override
11396         public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11397             synchronized (mWindowMap) {
11398                 WindowState windowState = mWindowMap.get(windowToken);
11399                 if (windowState == null) {
11400                     return null;
11401                 }
11402                 MagnificationSpec spec = null;
11403                 if (mAccessibilityController != null) {
11404                     spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11405                 }
11406                 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11407                     return null;
11408                 }
11409                 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11410                 spec.scale *= windowState.mGlobalScale;
11411                 return spec;
11412             }
11413         }
11414
11415         @Override
11416         public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
11417             synchronized (mWindowMap) {
11418                 if (mAccessibilityController == null) {
11419                     mAccessibilityController = new AccessibilityController(
11420                             WindowManagerService.this);
11421                 }
11422                 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11423                 if (!mAccessibilityController.hasCallbacksLocked()) {
11424                     mAccessibilityController = null;
11425                 }
11426             }
11427         }
11428
11429         @Override
11430         public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11431             synchronized (mWindowMap) {
11432                 if (mAccessibilityController == null) {
11433                     mAccessibilityController = new AccessibilityController(
11434                             WindowManagerService.this);
11435                 }
11436                 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11437                 if (!mAccessibilityController.hasCallbacksLocked()) {
11438                     mAccessibilityController = null;
11439                 }
11440             }
11441         }
11442
11443         @Override
11444         public void setInputFilter(IInputFilter filter) {
11445             mInputManager.setInputFilter(filter);
11446         }
11447
11448         @Override
11449         public IBinder getFocusedWindowToken() {
11450             synchronized (mWindowMap) {
11451                 WindowState windowState = getFocusedWindowLocked();
11452                 if (windowState != null) {
11453                     return windowState.mClient.asBinder();
11454                 }
11455                 return null;
11456             }
11457         }
11458
11459         @Override
11460         public boolean isKeyguardLocked() {
11461             return WindowManagerService.this.isKeyguardLocked();
11462         }
11463
11464         @Override
11465         public void showGlobalActions() {
11466             WindowManagerService.this.showGlobalActions();
11467         }
11468
11469         @Override
11470         public void getWindowFrame(IBinder token, Rect outBounds) {
11471             synchronized (mWindowMap) {
11472                 WindowState windowState = mWindowMap.get(token);
11473                 if (windowState != null) {
11474                     outBounds.set(windowState.mFrame);
11475                 } else {
11476                     outBounds.setEmpty();
11477                 }
11478             }
11479         }
11480
11481         @Override
11482         public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11483             boolean allWindowsDrawn = false;
11484             synchronized (mWindowMap) {
11485                 mWaitingForDrawnCallback = callback;
11486                 final WindowList windows = getDefaultWindowListLocked();
11487                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11488                     final WindowState win = windows.get(winNdx);
11489                     final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
11490                     final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs);
11491                     if (win.isVisibleLw()
11492                             && (win.mAppToken != null || isForceHiding || keyguard)) {
11493                         win.mWinAnimator.mDrawState = DRAW_PENDING;
11494                         // Force add to mResizingWindows.
11495                         win.mLastContentInsets.set(-1, -1, -1, -1);
11496                         mWaitingForDrawn.add(win);
11497
11498                         // No need to wait for the windows below Keyguard.
11499                         if (isForceHiding) {
11500                             break;
11501                         }
11502                     }
11503                 }
11504                 mWindowPlacerLocked.requestTraversal();
11505                 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11506                 if (mWaitingForDrawn.isEmpty()) {
11507                     allWindowsDrawn = true;
11508                 } else {
11509                     mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11510                     checkDrawnWindowsLocked();
11511                 }
11512             }
11513             if (allWindowsDrawn) {
11514                 callback.run();
11515             }
11516         }
11517
11518         @Override
11519         public void addWindowToken(IBinder token, int type) {
11520             WindowManagerService.this.addWindowToken(token, type);
11521         }
11522
11523         @Override
11524         public void removeWindowToken(IBinder token, boolean removeWindows) {
11525             synchronized(mWindowMap) {
11526                 if (removeWindows) {
11527                     WindowToken wtoken = mTokenMap.remove(token);
11528                     if (wtoken != null) {
11529                         wtoken.removeAllWindows();
11530                     }
11531                 }
11532                 WindowManagerService.this.removeWindowToken(token);
11533             }
11534         }
11535
11536         @Override
11537         public void registerAppTransitionListener(AppTransitionListener listener) {
11538             synchronized (mWindowMap) {
11539                 mAppTransition.registerListenerLocked(listener);
11540             }
11541         }
11542
11543         @Override
11544         public int getInputMethodWindowVisibleHeight() {
11545             synchronized (mWindowMap) {
11546                 return mPolicy.getInputMethodWindowVisibleHeightLw();
11547             }
11548         }
11549
11550         @Override
11551         public void saveLastInputMethodWindowForTransition() {
11552             synchronized (mWindowMap) {
11553                 if (mInputMethodWindow != null) {
11554                     mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
11555                 }
11556             }
11557         }
11558
11559         @Override
11560         public void clearLastInputMethodWindowForTransition() {
11561             synchronized (mWindowMap) {
11562                 mPolicy.setLastInputMethodWindowLw(null, null);
11563             }
11564         }
11565
11566         @Override
11567         public boolean isHardKeyboardAvailable() {
11568             synchronized (mWindowMap) {
11569                 return mHardKeyboardAvailable;
11570             }
11571         }
11572
11573         @Override
11574         public void setOnHardKeyboardStatusChangeListener(
11575                 OnHardKeyboardStatusChangeListener listener) {
11576             synchronized (mWindowMap) {
11577                 mHardKeyboardStatusChangeListener = listener;
11578             }
11579         }
11580
11581         @Override
11582         public boolean isStackVisible(int stackId) {
11583             synchronized (mWindowMap) {
11584                 return WindowManagerService.this.isStackVisibleLocked(stackId);
11585             }
11586         }
11587
11588         @Override
11589         public boolean isDockedDividerResizing() {
11590             synchronized (mWindowMap) {
11591                 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
11592             }
11593         }
11594     }
11595 }